Remove node from a linked list - c++

I have been stuck on this function to remove node from a list, if there are two names in the list they are both gone. If Anne and John are in the list and I want to delete Anne, then my list is empty, John is gone.
What am I missing to keep the connection in the list if I delete a node init?
bool ContactList::remove(string key)
{
NodePtr prev = NULL;
for(NodePtr temp = head; temp != NULL; temp = temp->link)
{
if(temp->data.key == key)
{
if(prev == NULL)
{
head = temp->link;
delete temp;
return true;
}
else
{
prev = temp->link;
delete temp;
return true;
}
}
}
return false;
}

You aren't keeping prev up to date in every iteration of your loop. You want something like:
prev = temp;
at the bottom of your for loop.

Try using this function
bool ContactList::remove(string key)
{
NodePtr prev = NULL;
for(NodePtr temp = head; temp != NULL; temp = temp->link)
{
if(temp->data.key == key)
{
if(prev == NULL)
{
head = temp->link;
delete temp;
return true;
}
else
{
prev->link = temp->link; // change.
delete temp;
return true;
}
}
prev = temp; // change.
}
return false;
}

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);
}
}

Remove Duplicates linked list

void RemoveDuplicates(Slist& l)
{
if (l.head == NULL) {
return;
}
Node* cur = l.head;
while (cur != NULL && cur->next != NULL) {
Node* prev = cur;
Node* temp = cur->next;
while (temp != NULL) {
if (temp->data == cur->data) {
prev->next = temp->next;
cur->next = prev->next;
temp = prev->next;
}
else {
prev = prev->next;
temp = temp->next;
}
}
cur = cur->next;
}
}
Hi, I want to remove duplicates from linked list (0 is NULL)
input: 1->2->2->4->2->6->0
outPut: 1->2->4->6->0
Result after I run my program is:
1->2->6
Where am I wrong? Please help me
Here is my solution for your problem:
bool alreadyExist(Node head)
{
Node cur = head;
while(cur.next != nullptr)
{
if(cur.next->data == head.data) {
return true;
}
cur = *cur.next;
}
return false;
}
void RemoveDuplicates(Slist& l)
{
if (l.head == nullptr) {
return;
}
Node* head = l.head;
Node* curPtr = l.head->next;
while(curPtr != nullptr)
{
if(alreadyExist(*curPtr) == false)
{
head->next = curPtr;
head->next->prev = head;
head = head->next;
curPtr = curPtr->next;
}
else
{
Node* backup = curPtr;
curPtr = curPtr->next;
// delete duplicate elements from the heap,
// if the nodes were allocated with new, malloc or something else
// to avoid memory leak. Remove this, if no memory was allocated
delete backup;
}
}
}
Important: The destructor of the Node-object is NOT allowed to delete the linked object behind the next and prev pointer.
It results, for your input-example, in the output 1->4->2->6->0. Its not totally exact the order, you want as output, but each number exist only one time within the output. It only add the last time of a duplicate number.
I don't really know, if you use C or C++, but because I prefer C++, I replaced the NULL with nullptr in the code. The delete can be removed, if the objects are not on the HEAP create with malloc or new.

Deleting a specific value from singly linked list?

I've been trying to delete a node if the data matches a specific value.
Here's my delete value method:
void del_value(int data)
{
Node *temp = head;
int i = 0;
while(temp!=NULL)
{
if(temp->data == data)
{
del_index(i);
i--; // Since the nodes count will be reduced after deleting, reducing the index by one.
}
i++;
temp = temp->next;
}
}
And here is my del_index method(Which is working correctly):
int getCount()
{
int i = -1;
Node *temp = head;
while(temp!=NULL)
{
temp = temp->next;
i++;
}
return i;
}
void del_index(int pos)
{
int count = getCount();
if(pos == 0)
{
del_start();
}
else if(pos == count)
{
del_last();
}
else if(pos<0 || pos>count)
{
cout<<"Out of range"<<endl;
return;
}
else
{
int i = 1;
Node *temp = head;
while(i<pos)
{
temp = temp->next;
i++;
}
Node *toDel = temp->next;
Node *forward = toDel->next;
temp->next = forward;
delete toDel;
}
}
And here is my main method:
int main()
{
Mylist l;
l.add_start(4);
l.add_start(4);
l.add_start(4);
l.del_value(4);
l.show();
}
But it stucks when it reaches del_value method inside loop. Any idea where am I missing?
Update: (Added del_first and del_last methods
void del_start()
{
if(head == NULL)
{
cout<<"List is empty"<<endl;
return;
}
else
{
Node *temp = head;
head = head->next;
delete temp;
}
}
void del_last()
{
if(head == NULL)
{
cout<<"List is empty"<<endl;
return;
}
else
{
Node *temp = head;
while(temp->next != NULL)
{
tail = temp;
temp = temp->next;
}
tail->next = NULL;
delete temp;
}
}
Your del_value method will not work because you delete the object being pointed to by 'temp' then you dereference it after (with "temp = temp->next").
For your example code, I would cache the 'next' value before your conditional, for example:
Node *next = temp->next;
if(temp->data == data)
{
del_index(i);
i--;
}
i++;
temp = next;
I am assuming you're doing this for practice purposes but I would add the following suggestions:
I wouldn't call del_index here but remove the node inline, within the del_value method. As you have the necessary pointers to be able to remove it. del_index has to traverse your list a second time.
I would also recommend using the containers within the stl instead of rolling your own to avoid encountering issues like this.

Linked list cstring insertion sort

This is my code for an insertion-sort, sorting via the cstring member of the node. The current code only inserts before the head. The code encapsulated in comments is the sorted insertion I am trying to make work. I'm thinking I have to use a predecessor and successor pointer, but maybe it's the comparison that is confusing me. Any help would be appreciated. Thanks!
#include <iostream>
#include "groclist.h"
void insert_item(Grocery_Item_Ptr &head, int quantity, const char name[])
{
bool exists = false;
bool done = false;
Grocery_Item_Ptr temp = NULL;
Grocery_Item_Ptr current = NULL;
Grocery_Item_Ptr pred = NULL;
Grocery_Item_Ptr succ = NULL;
if (head == NULL) {
head = new Grocery_Item;
head->quantity = quantity;
strncpy(head->name, name, MAX_ITEM_NAME_LEN);
head->next = NULL;
return;
}
else {
current = head;
while (current != NULL) {
if (strncmp(current->name, name, MAX_ITEM_NAME_LEN) == 0) {
current->quantity += quantity;
exists = true;
}
current = current->next;
}
if (exists) {
current = NULL;
return;
}
else {
current = head;
}
if (!exists) {
temp = new Grocery_Item;
temp->quantity = quantity;
strncpy(temp->name, name, MAX_ITEM_NAME_LEN);
/*
while (!done || current != NULL) {
if (strncmp(current->name, name, MAX_ITEM_NAME_LEN) < 0) {
pred = current;
succ = current->next;
current->next = temp;
temp->next = succ;
done = true;
}
if (!done) {
current = current->next;
}
}
*/
temp->next = head;
head = temp;
temp = NULL;
}
}
return;
}
One thing you are missing is keeping a reference to the predecessor while searching. This is necessary in order to keep the chain intact.
Here is a draft that should work (currently untested!):
while (!done || current != NULL)
{
//If we found the place to insert
if (strncmp(current->name, name, MAX_ITEM_NAME_LEN) < 0)
{
//If the place to insert was at head
if(pred == NULL)
{
//The new node becomes the head
head = temp;
}
else
{
//Set the previous nodes next to point at this node.
pred->next = temp;
}
//Always set the node to be inserted's next
//pointing to the node we should be inserted before
temp->next = current;
done = true;
}
if (!done)
{
//No match, keep looking but keep an updated pred pointer
pred = current;
current = current->next;
}
}
It's just pseudocode, but maybe it helps:
if(head == NULl)
{
//make newnode as head
}
if(head.name == new name)
{
//update quantity
}
if(head.name <new name)
{
//insert newnode before head
//make newnode as head
}
if (new name > head.name)
{
current = head;
succ = current.next;
while (succ && new name <succ.name)
{
curent = succ;
succ = succ.next
}
if(succ = NULL)
current->next = newnode
else
if new name = succ->name
update quantity
else
curent->next = newnode
newnode->next = succ;
}
I appreciate your input guys, if only for having me think about it in different ways. However my result is quite different, and I must truly thank my whiteboard.
if (strncmp(name, head->name, MAX_ITEM_NAME_LEN) < 0) {
temp->next = head;
head = temp;
temp = NULL;
}
else {
pred = head;
current = head->next;
do {
if (strncmp(name, current->name, MAX_ITEM_NAME_LEN) < 0) {
pred->next = temp;
temp->next = current;
done = true;
}
else if (current->next == NULL) {
current->next = temp;
done = true;
}
else {
pred = current;
current = current->next;
}
if (done) {
pred = NULL;
current = NULL;
}
} while (!done && current != NULL);
}

Crash, while printing contents of linked-list

I'm having some trouble printing out the contents of a linked list. I'm using an example code that I found somewhere. I did edit it a bit, but I don't think that's why it's crashing.
class stringlist
{
struct node
{
std::string data;
node* next;
};
node* head;
node* tail;
public:
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
return TRUE;
}
else
return FALSE;
}
}
BOOLEAN clear(std::string deldata)
{
node* temp1 = head;
node* temp2 = NULL;
BOOLEAN result = FALSE;
while (temp1 != NULL)
{
if (temp1->data == deldata)
{
if (temp1 == head)
head=temp1->next;
if (temp1==tail)
tail = temp2;
if (temp2 != NULL)
temp2->next = temp1->next;
delete temp1;
if (temp2 == NULL)
temp1 = head;
else
temp1 = temp2->next;
result = TRUE;
}
else // temp1->data != deldata
{
temp2 = temp1;
temp1 = temp1->next;
}
}
return result;
}
BOOLEAN exists(std::string finddata)
{
node* temp = head;
BOOLEAN found = FALSE;
while (temp != NULL && !found)
{
if (temp->data == finddata)
found=true;
else
temp = temp->next;
}
return found;
}
void print()
{
node* tmp = head;
while (tmp)
{
printf("%s", tmp->data.c_str());
tmp = tmp->next;
}
}
stringlist()
{
head=NULL;
tail=NULL;
}
};
My main() function is really simple:
int main()
{
stringlist mylist;
if (mylist.append("something"))
count++;
if (mylist.append("else"))
count++;
if (mylist.append("yet"))
count++;
cout<<"Added "<<count<<" items\n";
mylist.print();
return 0;
}
For some reason in Print() tmp is never NULL
in node, add a constructor to initialize next to null
As #rmn pointed out, you're not initializing the value of node->next.
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
tail->next = NULL; // <- this is the part that is missing
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
head->next = NULL; // <- it's also missing here.
return TRUE;
}
else
return FALSE;
}
}
You could solve this by having a default constructor for node:
struct node
{
std::string data;
node* next;
node() : next(NULL) { }
};
With the default constructor you won't need to add tail->next = NULL;.
You aren't initializing head->tail appropriately in append when head==NULL initially.
Correct. That's because tail is only NULL in your code when the linked list is initially created. After you add a node, you set tail = head, and from that point in time, every time you add an element, you set tail->next = new node, and then tail = tail->next... so that tail->next always = tail.