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);
}
}
Related
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;
}
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.
Here using the function returnReverseLinkedList I am returning the reversed linked list of the given linked list. But the problem with this approach is that i lose the original linked list. So I make another fucntion called createReversedLinkedList to make a copy of the original linked list and reverse the copy and maintain possession of both.
unfortunately createReversedLinkedList is giving Runtime error.
obviously my end goal is to check if the given linked list is palindrome or not. This issue is just a stepping stone.
Could someone tell me why?
//Check if a linked list is a palindrome
#include <iostream>
using namespace std;
class node
{
public:
int data;
node *next;
node(int data)
{
this->data = data;
this->next = NULL;
}
};
node *returnReverseLinkedList(node *head)
{
// Will Lose original Linked List
if (head == NULL)
return NULL;
else if (head != NULL && head->next == NULL)
return head;
node *prev = NULL;
node *curr = head;
node *tempNext = head->next;
while (tempNext != NULL)
{
curr->next = prev;
prev = curr;
curr = tempNext;
tempNext = tempNext->next;
}
curr->next = prev;
return curr;
}
node *createReversedLinkedList(node *head)
{
if (head == NULL)
return NULL;
else if (head != NULL && head->next == NULL)
return NULL;
else
{
node *temp = head;
node *newHead = NULL;
node *newTail = NULL;
while (temp != NULL)
{
node *newNode = new node(temp->data);
if (newHead == NULL)
{
newHead = newNode;
newTail = newNode;
}
else
{
newTail->next = newNode;
newTail = newNode;
}
}
return returnReverseLinkedList(newHead);
}
}
bool check_palindrome(node *head)
{
node *original = head;
node *reverse = returnReverseLinkedList(head);
while (original->next != NULL || reverse->next != NULL)
{
if (original->data != reverse->data)
return false;
cout << "debug 2" << endl;
original = original->next;
reverse = reverse->next;
}
return true;
}
// #include "solution.h"
node *takeinput()
{
int data;
cin >> data;
node *head = NULL, *tail = NULL;
while (data != -1)
{
node *newnode = new node(data);
if (head == NULL)
{
head = newnode;
tail = newnode;
}
else
{
tail->next = newnode;
tail = newnode;
}
cin >> data;
}
return head;
}
void print(node *head)
{
node *temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
int main()
{
node *head = takeinput();
node *revese2 = createReversedLinkedList(head);
print(revese2);
// bool ans = check_palindrome(head);
// if (ans)
// cout << "true";
// else
// cout << "false";
// return 0;
}
As asked by the OP, building a reversed linked is simply done by building as you would a stack (e.g LIFO) rather than duplicating the same original forward chain. For example:
node *createReversedLinkedList(const node *head)
{
node *newHead = NULL;
for (; head; head = head->next)
{
node *p = new node(head->data)
p->next = newHead;
newHead = p;
}
return newHead;
}
Note we're not hanging our copied nodes on the tail of the new list; they're hanging on the head of the new list, and becoming the new head with each addition. That's it. There is no need to craft an identical list, then reverse it; you can reverse it while building the copy to begin with.
A note on the remainder of your code. You have a dreadful memory leak, even if you fix the reversal generation as I've shown above. In your check_palindrome function, you never free the dynamic reversed copy (and in fact, you can't because you discard the original pointer referring to its head after the first traversal:
bool check_palindrome(node *head)
{
node *original = head;
node *reverse = returnReverseLinkedList(head); // only reference to reversed copy
while (original->next != NULL || reverse->next != NULL)
{
if (original->data != reverse->data)
return false; // completely leaked entire reversed copy
original = original->next;
reverse = reverse->next; // lost original list head
}
return true;
}
The most obvious method for combating that dreadful leak is to remember the original list and use a different pointer to iterate, and don't leave the function until the copy is freed.
bool check_palindrome(const node *head)
{
bool result = true;
node *reverse = returnReverseLinkedList(head);
for (node *p = reverse; p; p = p->next, head = head->next)
{
if (p->data != head->data)
{
result = false;
break;
}
}
while (reverse)
{
node *tmp = reverse;
reverse = reverse->next;
delete tmp;
}
return result;
}
What I am trying to do is check if node after value is specific number and if is, then delete previoues node.
Something like:
1,2,3,4,5,4
if next node number is 4 then delete this node.
1,2,3,4,5,4 -> 1,2,4,4
node* temp = head;
while (head != NULL) {
if (head->next->number == 4) {
delete temp;
}
head = head->next;
}
Struggling at this moment as compiler crashes.
You delete the head before you advance it:
node *temp = NULL;
while (head->next != NULL) {
if (head->next->number == 4) {
temp = head;
}
if ( temp == NULL ){
head = head->next;
}
else{
head = head->next->next;
delete temp;
temp= NULL:
}
}
I have implemented a linked list but I find that removal of the last element in the linked list always fails. I checked my code several times but didn't find the logic mistake. Remove from the head and middle node works fine. Below is my code:
#include<iostream>
using namespace std;
template<typename T>
class Node{ //
private:
T val;
Node *next;
Node *prev;
public:
Node(T value){
val = value;
next = nullptr;
prev = nullptr;
}
~Node(){
if(prev != nullptr){
prev->next = next;
}
if(next != nullptr){
next->prev= prev;
}
}
T& getVal(){ //
return val;
}
Node* getNext(){
return next;
}
Node* getPrev(){
return prev;
}
//insert node after this node
void insert(Node *n){
if(next != nullptr){
next->prev = n;
}
n->next = next;
n->prev = this;
next = n;
}
void deleteNode(){
if(prev != nullptr && next != nullptr){
prev->next = next;
next->prev = prev;
}
}
};
//build a linked list with deletion and push back function
template<typename T>
class LList{
private:
Node<T> *head;
Node<T> *tail;
public:
LList(){
head = nullptr;
tail = nullptr;
}
~LList(){
if(nullptr != head){
while(head->getNext() != nullptr){ //
delete head->getNext();
}
delete head;
}
}
void push_back(T val){
Node<T>* n = new Node<T>(val);
if(head == nullptr){
head = n ;
tail = head;
}
else{
tail->insert(n);
tail = n;
}
}
void deleteItem(T item){
Node<T> *node = head;
//delete head
if(node->getVal() == item){
head = node->getNext();
node->deleteNode();
return;
}
//delete middle and tail
while(node->getVal() != item && node->getNext() != nullptr ){
node = node->getNext();
}
if(node->getVal() == item && node == tail){
tail = node->getPrev();
node->deleteNode();
return;
}
if(node->getVal() == item && node != tail){
node->deleteNode();
return;
}
else {
cout<<"didnt find the item "<<item<<endl;
}
}
void print(){
Node<T> *node = head;
while(node->getNext() != nullptr){
cout<<node->getVal()<<endl;
node = node->getNext();
}
cout<<node->getVal()<<endl;
}
};
int main(){
LList<double> list;
list.push_back(3.13);
list.push_back(2.8);
list.push_back(23);
list.push_back(4);
list.print();
list.deleteItem(3.13);
list.deleteItem(2);
list.deleteItem(4);
list.print();
return 0;
}
Here it is:
void deleteNode(){
if(prev != nullptr && next != nullptr){
prev->next = next;
next->prev = prev;
}
}
};
For the last element i guess that next equals nullptr and so the whole condition fails.
What I don't understand, is why removing the first element doesn't fail too, you probably should x-check your code for this.
[edit]
Here's my solution to fix this bug, it's basically the same as in the destructor for node:
void deleteNode(){
if(prev != nullptr){
prev->next = next;
}
if(next != nullptr){
next->prev= prev;
}
};
I think all cases have been considered in this:
Head := prev == null & next->prev = nullptr (assuming prev for this node was nullptr before)
Middle := prev->next = next & next->prev = prev
Tail := prev->next = null (assuming as above) & next == null
Head&Tail := prev == null & next == null (Only element of the list is deleted, so no references to be changed)
[/edit]