Remove Node in Doubly Linked List (C++) - c++

This is my remove function for deleting a node with the element item. I'm getting a seg fault and I'm pretty sure it's because temp -> prev is the front sentinel so it's not technically in the doubly linked list. And if that's correct, how do I actually go about preventing this? Any help would be appreciated.
EDIT: Just updated the code, but still coming out with a Seg fault
void list::remove(const list_element & item)
{
list_node* temp = _front;
for (int i = 0; i < _size; i++)
{
if (temp -> next -> data == item)
{
if (temp -> prev == _front)
{
_front = temp -> next;
}
else if (temp -> next == _rear)
{
temp -> prev -> next = _rear;
}
else
{
temp -> prev -> next = temp -> next;
temp -> next -> prev = temp -> prev;
}
}
delete temp;
}
}

You want to go through the list node by node using a while() loop. Since _front is a sentinel you don't need an explicit check for whether the next or prev node is the head or tail.
void list::remove(const list_element& item) {
list_node* current = _front;
while (current->next != nullptr) {
if (current->next->data == item) {
current->next = current->next->next;
if (current->next != nullptr) {
delete current->next->prev;
current->next->prev = current;
}
break;
}
current = current->next;
}
// update pointer to rear if it changed
if (current->next == nullptr)
_rear = current;
}

Related

Deleting a key from a circular linked list

void deletenode(string key) {
if (last == NULL) {
cout << "your circular linked list is an empty one" << endl;
}
else {
node* p = last->next;
node* prev = last;
do {
if (p->title == key) {
node* temp = p;
prev->next = p->next;
delete(temp);
}
else {
p = p->next;
prev = prev->next;
}
} while (p != last->next);
}}
I was trying to delete a node with key value. For instance, if node p->title is my key then I want to delete that node. However, I implemented it with other values but the code doesn't seem to work or delete a node with key value from my circular linked list. What is the mistake in the function?
circular linked list value "cat", "dog", "rat", "horse", the key to be deleted was "dog". When I traverse throughout the linked list after the deletion it still printed everything including "dog", which means deletion didn't work.
Anytime you write a "delete from the linked list" function, you have to account for the possibility that you are deleting from the "head" or whatever pointer you are referencing with the list. The common pattern is for the function to return the new head of the list if it changed, else return the current head.
Node* deletenode(Node* head, const string& key) {
// empty list
if (head == nullptr) {
return nullptr;
}
// single item list
if (head->next == nullptr || head->next == head) {
if (head->title == key) {
delete head;
head = nullptr;
}
return head;
}
// two or more item list, possibly circular
Node* prev = head;
Node* current = head->next;
Node* first = current;
while (current && current->title != key) {
prev = current;
current = current->next;
if (current == first) {
break;
}
}
if (current == nullptr || current->title != key) {
return head; // not found
}
prev->next = current->next;
if (current == head) {
head = current->next;
}
delete current;
return head;
}
I don't see the full code so I can't make a comment I tried to implement the function, hope it helps you with the comments.
void deleteNodeWithKey(node* head, string key)
{
node *curr = head;
node *last , *temp;
//Search for last node
while (curr->next != head)
{
curr = curr->next;
}
last = curr;
//If head is the desired key, make head's next new head
//and connect last node to new head
if (head->key == key)
{
temp = head->next;
delete head;
head = temp;
last->next = head;
return;
}
temp = head->next;
//Search for node with the given key
node *prev = head;
while (temp != head)
{
if (temp->key == key)
{
prev->next = temp->next;
delete temp;
return;
}
temp = temp->next;
prev = prev->next;
}
//If function gets here, key was not found
}
I made some changes to your code
void deletenode(string key) {
if (last == NULL) {
cout << "your circular linked list is an empty one" << endl;
}
else {
node* prev = last;
// If head is to be deleted
if (last->title == key) {
while (prev->next != last)
prev = (prev)->next;
prev->next = last->next;
free(last);
last = prev->next;
return;
}
node* p = last->next;
do {
if (p->next->title == key) {
node* temp = p->next;
p->next = temp->next;
delete(temp);
}
else {
p = p->next;
prev = prev->next;
}
} while (p != last->next);
}
}

Deleting node in a double linked list is not working

This is a basic function that takes an iterator position and deletes the node in this position but it gives me a runtime error. what am i doing wrong?
iterate erase(iterate position)
{
iterate i;
Node<T>* temp = head;
if (head == NULL) {
cout << "empty list" << endl;
}
else if (position.pointer == head) {
head = temp->next;
temp->next->previous = NULL;
delete position.pointer;
}
else {
while (temp != NULL) {
if (temp == position.pointer->previous) {
temp->next = position.pointer->next;
temp->next->previous = temp;
i.pointer = temp->next;
delete position.pointer;
return i;
}
}
}
Your function is lacking adequate return statements. There are multiple flows that can cause the function to exit, but only one of them has a return statement. So the return value will largely be indeterminate, causing undefined behavior for any caller that tries to use the return value.
In any case, your while loop iterates forever, because you are not updating temp on each iteration of the loop. You also have a NULL pointer dereference if position is pointing at the last node in the list, as you are not checking the new temp->next for NULL before accessing temp->next->previous.
But, you really don't need the while loop at all. The thing about a double-linked list is that, given any node in the list, you have direct access to the nodes that are surrounding it on both sides. So there is no need to iterate the list hunting for nodes.
Try something more like this instead:
iterate erase(iterate position)
{
Node<T> *temp = position.pointer;
if (!temp) return end();
Node<T> *next = temp->next;
Node<T> *previous = temp->previous;
if (next) next->previous = previous;
if (previous) previous->next = next;
if (temp == head) head = next;
//if (temp == tail) tail = previous;
delete temp;
iterate i;
i.pointer = next;
return i;
}
Alternatively:
iterate erase(iterate position)
{
Node<T> *temp = position.pointer;
if (!temp) return end();
Node<T> *dummy; // <-- only if no tail ...
Node<T> **previous = (temp->next) ? &(temp->next->previous) : &dummy/*&tail*/;
Node<T> **next = (temp->previous) ? &(temp->previous->next) : &head;
*previous = temp->previous;
*next = temp->next;
delete temp;
iterate i;
i.pointer = *next;
return i;
}

Implementing pop function with doubly linked list

void Stack::pop()
{
Node* temp;
if(top == NULL)
return;
temp = top;
top = top->prev;
top = top->next;
delete temp;
}
So I am having trouble implementing the pop function in a doubly linked list. Whenever I build my compiler crashes. The code above is what I'm struggling with. I am really unsure on how to actually unlink my top node from my list. If you guys can explain the pop function in a doubly linked list that would be great.
void Stack::ToString()
{
//needs to be implemented
Node* cursor = top; //create a temporary pointer for top
while(cursor->next != NULL) //When debugging this is where it crashes.
cursor = cursor->next;
while(cursor != NULL)
{
cout << cursor->content << endl;
cursor = cursor->prev;
}
}
The logic in the function is flawed.
Let' say you have two node in the linked list:
top -> +--+
| |
+--+
(next) ^ | (prev)
| v
n2 -> +--+
| |
+--+
Then, top->prev = n2 and n2->next = top.
When you execute:
top = top->prev; // Now top is n2
top = top->next; // Now top is what it used to be start with.
You did nothing in the list to pop top from the top of the list.
The fix to this problem depends on whether the list is circular or not.
If the list is not circular, you can do:
Node* prev = top->prev;
Node* next = top->next;
if ( prev != NULL )
{
prev->next = next;
}
if ( next != NULL )
{
next->prev = prev;
}
top->next = NULL;
top->prev = NULL;
If the list is circular, the logic needs to be a little bit more elaborate.
Imagine the list like this pic:
And the code is clear to understand.
struct Node {
int data;
struct Node* next;
struct Node* prev;
};
void Pop(struct Node *&head) {
if (head != NULL) {
// if list hase just one item, set head to null
if (head->next == NULL) {
head = head->next;
}
else {
// copy head to temp node
Node *tmp = new Node;
tmp = head;
// traverse list to raech end of it
while (tmp->next->next != NULL)
tmp = tmp->next;
// deallocate last node
delete tmp->next;
tmp->next = NULL;
}
}
}
For printing the list:
void Print(struct Node *&head) {
if (head == NULL) {
std::cout << "list is empty!\n";
}
else {
while (head != NULL) {
std::cout << head->data << " ";
head = head->next;
}
}
}

Doubly linked list: delete a node

I'm trying to delete a node in a doubly linked list, but the problem here is that when I have the list: 7-6-5-4-3-2-1, and try to delete 3, I get 7-6-5-4-3, I can't figure out the error. Please help!
void RemoveItem(int itm)
{
if (Head->item == itm) {
Head = Head -> Next;
cout<<"\nItem is at 1st node & removed\n";flag=1;
}
else if (Head->Next == NULL) {
cout<<" \n This is 1-node list & item not in it\n";
}
else {
node *current, *del = Head;
while(del->Next != NULL && del->item != itm) {
del = del->Next;
}
current = del;
current->Next = del->Next;
del->Next->previous = current;
delete(del);
del->Next = NULL;
flag = 1;
}
}
To delete a node you iterate until you reach the node of deletion del then set:
pseudocode:
del.prev.next = del.next
and
del.next.prev = del.prev
This makes no sense:
current = del;
current->Next = del->Next;
because it is the same as
del->Next = del->Next;
Try something like this
// some global int flag = 0
// some global node* Head pointing to head of list
void RemoveItem(int itm) {
if (Head->item == itm) {
node* del = Head;
Head = Head -> Next;
delete(del);
cout<<"\nItem is at 1st node & removed\n";
flag=1;
return;
}
if (Head->Next == NULL) {
cout<<" \n This is 1-node list & item not in it\n";
return;
}
node* current = Head;
node* del = Head;
while(del->Next != NULL && del->item != itm) {
del = del->Next;
}
// reached with del->Next == NULL || del->item == itm
current = del->previous;
if (del->Next == NULL) {
// at end of list
if (del->item != item) {
// item not found
// todo: signal error
return;
}
current->Next = NULL;
} else {
del->Next->previous = current;
current->Next = del->Next;
}
delete(del);
flag = 1;
}
Note: I fixed many bugs and tried to keep it within your logic. I would have written it different.

Implementing fa unction that adds and sorts data in a singly linked list (addsort)?

I'm very new to C++ so it's a bit hard to understand the syntax sometimes. Anyways, I'm supposed to implement a function that adds and sorts the data given into a linked list. For example if I pass 2 into the list [1,4,5] then I should get [1,2,4,5]
Here is what I have written so far, and no it does not work, I keep getting "blah blah not declared in this scope"
void addSorted(Data * ){
temp = 0;
if (head == NULL) {
head = new LinkNode(newData);
}
else {
LinkNode * current = head;
while (current->next != NULL) {
current = current->next;
}
if(current->data > current->next->data){
temp = current->data;
current->data = current->next->data;
current->next->data = temp;
}
current->next = new LinkNode(newData);
}
}
Someone please help me, I'm using the struct LinkNode I think which is already given, in addition to a bunch of other functions like add, insert, remove, get, and size
I'm not looking to just get the answer, I need to know why what I have isn't working.
Hope that you have really put your effort in it..I am posting the whole function for inserting data into list in sorted order which I had written long time back
void addData(node * head, int data){
if(head == NULL) { // First node
node * temp = new node;
temp -> data = data;
temp -> next = NULL;
head = temp;
root = head;
}else{
node * prev = NULL;
while(head -> next != NULL){ // Sorted Addition Logic is HERE
if(data >= head -> data){
prev = head;
head = head -> next;
continue;
}else{
node * temp = new node;
temp -> data = data;
temp -> next = head;
if(prev != NULL)
prev -> next = temp;
else
head = temp;
break;
}
}
if(head -> next == NULL){
node * temp = new node;
temp -> data = data;
head -> next = temp;
temp -> next = NULL;
}
}
}
Seeing your code, it seems that your logic itself is wrong...you are always ending on the last node (while loop) and in the next if statment you are trying to compare the data of the next node which is not present