deleting a node anywhere in a linked list - c++

I know how to remove a node from the front of a singly linked list, but I have no idea how to remove one from any arbitrary location.
In my specific problem, I continue to pass an integer value x into each node in the linked list. I can add and delete, but there is a function I need to write where if I've identified two x's that are the same, I delete the other instance.
I can give examples of my code if anyone needs examples of what I've done so far. Thanks for any and all responses
Also, I'm working with a singly linked list.

this is a disadvantage that singly linked list has. It requires iteration to perform deletion since you can not find the previous element of an arbitrary element. What you can find is its next element. You have to iterate from the head of the lists to find its previous element.
Hope this helps.

Because each node only has a link to the subsequent node, you would have to iterate over the entire list to obtain the previous element, then link the previous with the next node. (next, as in the one after that you wish to remove)

What I was doing, when I was looking into lists, and what not is: when iterating through list, I kept the pointer to the previous element in a separate variable, and if I decided that I needed to delete current element, I already had the pointer to the previous element at hand.
So, pseudo-code wise (to better illustrate it), it would be something like this:
prevValue = NULL
for curValue = root; curValue != NULL; curValue = curValue->Next
LOOP
IF *need to delete curValue*
THEN
IF prevValue == NULL
THEN
root = curValue->Next
delete curValue
curValue = root
ELSE
prevValue->Next = curValue->Next
delete curValue
curValue = prevValue
END IF
END IF
prevValue = curValue
END LOOP

noderemove(nodehead,int d){
if(head==NULL)
cout<<"empty linked list\n";
else {
node*curr=head,*pre=NULL;
while (curr!=NULL && curr->data !=d)
{
pre=curr;
curr=curr->next;
}
if(curr==NULL)
cout<<"Mahloch this number not found\n";
else {
if(pre==NULL)
head=curr->next;
else
pre->next=curr->next;
curr->next=NULL;
delete(curr); }
}return head;
}

Related

Removing duplicates from a sorted list (New Approach)

This is my program for removing duplicates from a sorted linked list. I am traversing from the head node of the linked list and using temp1 variable, I am checking whether there are any duplicates of the same value. If we find a data which is different from the current node, then we link that to current node and make it current node and repeat the process.
Here is the question:-
https://leetcode.com/problems/remove-duplicates-from-sorted-list/
ListNode* deleteDuplicates(ListNode* head) {
ListNode *curr=head,*temp1,*forw;
while(curr!=NULL)
{
//temp1 checks for next distinct element
temp1=curr->next;
while(temp1!=NULL)
{
//checking if the value at temp1 is distinct from current
if(temp1->val!=curr->val)
{
forw=temp1; //stored the distinct value in forw for reference to curr
break;
}
temp1=temp1->next;
}
curr->next=forw; // linked the distinct value to current
curr=curr->next;
}
return head;
}
But, the program is giving TLE(Time Limit Excedeed) Error.I have dry runned the code and it's working fine for me. I think i am missing some edge. Any help will be greatly appreciated?
You have UB for list of one element, as forw is then used uninitialized.
(that UB should probably do, in your case, infinite loop, so TLE).

Indexed singly linked list

I want to create a singly linked list with. I already have an implementation that does not permit indexing on it.
I would like to add this feature but I am not sure how to do that.
So basically the head should have index "1". But I can't figure it out myself what am I supposed to do in If statement to increase the index by 1 each step.
void AddNode (int addData)
{
nodePtr NewNode = new node;
NewNode->next = NULL;
NewNode->data = addData;
if (head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = NewNode;
NewNode->index;
}
else
{
head = NewNode;
NewNode->index = 1;
}
}
You mean for the ability to do something like get a linked list node via a get(index)?
Also, your head should not have index 1, it should be 0. This does not comply with standard practice of zero-based indexing.
A linked list does not technically have indexes nor should it store them. It seems like a linked list might not be the right data structure for what you are doing, however you can treat it like so with a loop like this (excuse if my c++ syntax is rusty)
int get(int index) {
Node current = head;
for (int x = 0; x < index; x++) {
if (current->next == null) {
//some sort of error handling for index out of bounds
} else {
current = current->next;
}
}
return current->data
}
get(2) would return the 3rd element of the list.
Graph for the structure
Why do you want to add it to the end of the list? Just simply add the new node to the front.
I don't think it is necessary to follow the order of 1,2,3.... Instead, you can do it reversely
Before you add a new node, you visit the head and find the index(i)of it. When you add the new one, the index of this one will be i+1.
Two advantages:
- It doses not change anything when you loop through this list.
- You know how many you have added into this list.
So what you really want to do is to add the ability to index elements of a linked list.
There is no need to actually store the index anywhere (as you don't really store the index of an array/vector element as the type and the address of the first element of the array is everything you need to retrieve the i-th element).
The only information you want to keep is the length of the list since computing it is costly because you have to traverse the list from head to tail every time you need it. Once you have this information the addNode should only update the size of the list.
As you already know accessing the i-th elements of a linked list is also costly (compared to a vector), but it is easy to code.
Something like the following should work:
void get(Node* head, size_t pos) {
while (head && pos--)
head = head->next;
return pos<=0 ? head : nullptr ;
}
It traverses the list from the head until it either reaches the end (head is nullptr) or pos is <=0.
Once you are out of the loop if pos>0 means that the list is shorter than pos otherwise you can return head (which will point to the pos-th element)

c++ understanding a circular doubly linked list

I'm having a problem figuring out how to set my ptr's for prev and next when I add a node with at least one existing node. Adding the first node is easy, just setting the ptrs to the front. I need help viewing this mentally, also this program is a queue so each node gets added to the back of the list.
if (Empty())
{
front = new qnode;
front->next=front;
front->prev=front;
front->data = item;
}
else if (front->prev=front)
{
front->prev = new qnode;
front->prev->next= front;
front->next=front->prev;
front->prev->data = item;
}
else
{
}
What i have now still not getting it
else
{
front->prev= new qnode;
front->prev->data= item;
front->prev->next=front;
front->prev=front->prev->prev;
}
I hope this image helps a bit
I have created pictures for 1 item 2 items and 3 items
the pointers just point to the actual object meaning the black rectangle is the whole object if front being blue and prev being brown(those are just there as references)
I really hope this helps linked list can get really tricky and drawing always helps me.
so to add the item at the front of the list you have some code like this:
//ok first I'll define some variables for you
//last === the last node in the list
//head === the first node in the list
//node === the new node you are adding;
qnode node = new qnode;
node.data = data; //whatever data you are holding
node->next = last; //last element in the list since it is circular;
node->prev = head; //you want the new node to point the the first node since it's getting added before that;
head->next = node; //you want the head of the node to point to the new node not the last item
last->prev = node; //last node now should point to the new node you just added not the head;
I am not sure why you need an else if, as I think the case with one element is not different from that with multiple elements. In any case you have a syntax error there - you wanted to write == instead of =.
More to the point, what you want to do is:
Create a new qnode
Set the data of the new node to the item
Set the next of the new node to the front
Set the prev of the new node to front->prev
Set the prev of the front to the new node.
You may check for yourself on a piece of paper how this works.
In a circular doubly linked list, you have 2 pointers, one to the head and one to the tail (last element in the list). If a element has a next, the next element's prev should be the element pointing at it through it's next element.
Your head pointer should never move unless the head element is removed. Your tail will move along always ensuring that the element it points to has head as it's next element.
Hopefully this helps
Since you always add at the end, the case of a queue with a single element is identical with the case of a list with multiple elements. Take a paper and a pen, make some sketches and it will come very easy to you.

How I can get back in singly linked list?

I have a singly linked list. From each node in the list, I can get to the next element. Is it possible instead to get to the previous element? Note that I cannot use a doubly linked list because of memory constraints.
If you must use a singly linked list, then one way to approach this is to traverse the list again until you find the prior item. You will know when you are at the prior item when its Next field is equal to the current item.
Pseudo C code:
Node* GetPreviousNode(Node* currentNode)
{
Node* iteratorNode = GetHeadNode();
while (iteratorNode != NULL)
{
if (iteratorNode->Next == currentNode)
return iteratorNode;
iteratorNode = iteratorNode->Next;
}
return NULL;
}
You can't, you have to use a double-linked-list where you have a pointer to the previous and next elements. A single linked list simply points to the next element and doesn't keep track off previous elements.
Try this:
http://en.literateprograms.org/Doubly_linked_list_(Java)
There a 2 different methods for traversing a singly linked list both ways.
Method 1: The link field (of the structure) is actually a 'difference' field. The link is computed
as the address of the next item minus the address of the previous item, therefore ...
next = address of the previous item + link of the current item.
prev = address of the next item - link of the current item.
If you can do arithmetic with pointers, you will be in business. If not, you will have to use a union (in C++) or use method 2. See: Algorithms + Data Structures = Programs by Niklaus Wirth - Prentice-Hall
1976 - page 19.
Method 2: The link field is the 'exclusive or' (^) of the address of the previous item with the address
of the next item. Exclusive or is an inverse of itself, therefore ...
next = address of the previous item ^ link of the current item.
prev = address of the next item ^ link of the current item.
If you have a node that you are sure of, is before the given node in a singly linked list, then you can make a function:-
struct node* prev(struct node* before, struct student_detail* current)
{
struct student_detail* temp = before;
while (temp->next != NULL)
{
if(temp->next == current)
{
return temp;
}
temp = temp-> next;
}
return NULL;
}
and use it as in
example_node = prev(before, example_node);
If you have head, you can always use that as the prev node.
You can theoretically go back, it generally beats the whole concept behind a singly linked list and it's more trouble than necessary but if you have to, here's how to implement it in C, assuming of course, you already declared your Node struct:-
Node* go_back(Node* head, Node* current_node){
//Traverse the linked list until we discover the next node
//in our traversal points to our current node
Node* previous_node = head;
while(previous_node->next != NULL){
if(previous_node->next == current_node)
return previous_node->next; //found previous node
previous_node = previous_node->next;
}
return previous_node //we found nothing, give up
}

Insertion in ordered linked list

I'm trying to insert a node in a linked list so that the nodes are ordered in ascending mode by de idx parameter.
void add(int i){
if(find(i)==NULL){ //if node does not exist
node *m=new node;
m->idx=i;
m->values=NULL;
m->next=NULL;
if(list==NULL){ //if list is empty
list=m;
return;
}
if(i < list->idx){ //if the new node comes before the head node
m->next=list;
list=m;
return;
}
//if the new node is bigger than the maximum node index in the list
if(i > maxIdx(list)){
node *last=lastNode(list);
last->next=m;
}
//else normal insertion
node *prev=list;
node *curr=list->next;
while(curr!=NULL){
if( i < curr->idx){
m->next=curr;
prev->next=m;
return;
}
prev=curr;
curr=curr->next;
}
}
}
Edited with correct implementation, the fourth if was missing before.
It seems correct to me as well, as far as segfault is concerned. However, you don't consider the case when i is greater than the largest number in the list. In this case, you should insert i at the end of the list. So try fixing this bug first, maybe it will fix the segfault as well (which is coming from elsewhere, maybe from your find() implementation).
Now it seems that is the answer (as your comment on my comment confirms it).