C++ Linked List deleting the wrong item [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to review data structures and implement a basic linked list. When I run this code, I get the following output:
3 4 6
1 was found and deleted 4 was found and deleted
3
4 should be deleted, but obviously 1 should not, and I'm wondering where the error in my code/logic is.
Thanks in advance for any help.
#include <iostream>
using namespace std;
class List {
private:
struct node {
int data;
node * next;
};
node * head;
node * curr;
node * temp;
public:
List();
void addNode(int newData);
void deleteNode(int delData);
void printList();
};
int main() {
List test;
test.addNode(3);
test.addNode(4);
test.addNode(6);
test.printList();
cout << endl << endl;
test.deleteNode(1);
test.deleteNode(4);
cout << endl << endl;
test.printList();
}
List::List(){
head = NULL;
curr = NULL;
temp = NULL;
}
void List::addNode(int newData){
node * n = new node;
n->next = NULL;
n->data = newData;
if (head != NULL) { // List is intact
curr = head; // if List is not empty, make curr equal to the head, and start at the beginning of the list.
while(curr->next != NULL) { // Get to last item on the list
curr = curr->next;
}
curr->next = n; // Use the last item, and point to the new node.
}
else { // empty list
head = n; // new node is the head of the list.
}
}
void List::deleteNode(int delData){
node * n = new node;
temp = head;
curr = head;
if (head != NULL) {
while (curr->next != NULL && curr->data != delData) {
temp = curr;
curr = curr->next;
}
if (curr == NULL) {
cout << delData << " was not found in the list\n";
delete n;
}
else {
n = curr;
curr = curr->next;
temp->next = curr;
delete n;
cout << delData << " was found and deleted\n";
}
}
}
void List::printList(){
curr = head;
while (curr != NULL) {
cout << curr->data << endl;
curr = curr->next;
}
}

The following line allocates a new node.
node * n = new node;
As already pointed out in the comments, it is not clear why the deleteNode() is doing that. The subsequent lines of delete n is actually deleting this new node, not one of the nodes in the list.
I would try writing deleteNode() something like this:
void List::deleteNode(int delData) {
// Empty list
if (!head) return;
// The first node is to be deleted
if (head->data == delData) {
node * old_head = head;
head = head->next;
delete old_head;
return;
}
// A non-first node is to be deleted
for (node * cur = head; cur; cur = cur->next) {
if (cur->next && cur->next->data == delData) {
node * del_node = cur->next;
cur->next = cur->next->next;
delete del_node;
break;
}
}
}

Actually the problem in your code was that the condition :
curr-> next !=NULL had to be replaced by curr!= NULL
since the code stops one step before it requires to stop.
Here is your working code:
#include <iostream>
using namespace std;
class List {
private:
struct node {
int data;
node * next;
};
node * head;
node * curr;
node * temp;
public:
List();
void addNode(int newData);
void deleteNode(int delData);
void printList();
};
int main() {
List test;
test.addNode(3);
test.addNode(4);
test.addNode(6);
test.printList();
cout << endl << endl;
test.deleteNode(1);
test.deleteNode(4);
cout << endl << endl;
test.printList();
}
List::List(){
head = NULL;
curr = NULL;
temp = NULL;
}
void List::addNode(int newData){
node * n = new node;
n->next = NULL;
n->data = newData;
if (head != NULL) { // List is intact
curr = head; // if List is not empty, make curr equal to the head, and start at the beginning of the list.
while(curr->next != NULL) { // Get to last item on the list
curr = curr->next;
}
curr->next = n; // Use the last item, and point to the new node.
}
else { // empty list
head = n; // new node is the head of the list.
}
}
void List::deleteNode(int delData){
node * n = new node;
temp = head;
curr = head;
if (head != NULL) {
while (curr!= NULL && curr->data != delData) {
temp = curr;
curr = curr->next;
}
cout<<temp->data<<" ";
if (temp->next == NULL) {
cout << delData << " was not found in the list\n";
delete n;
}
else {
n = curr;
curr = curr->next;
temp->next = curr;
delete n;
cout << delData << " was found and deleted\n";
}
}
}
void List::printList(){
curr = head;
while (curr != NULL) {
cout << curr->data << endl;
curr = curr->next;
}
}

As #drescherjm said, that extra allocation could be skipped.
The final deletenode function is:
void List::deleteNode(int delData){
node * n ;
temp = head;
curr = head;
if (head != NULL) {
while (curr!= NULL && curr->data != delData) {
temp = curr;
curr = curr->next;
}
cout<<temp->data<<" ";
if (temp->next == NULL) {
cout << delData << " was not found in the list\n";
// delete n;
}
else {
n = curr;
curr = curr->next;
temp->next = curr;
delete n;
cout << delData << " was found and deleted\n";
}
}
}

Related

How to use point to next node when deleting elements in C++

I have previously posted some part of this task here.
I am now implementing a method that removes an element at a given index. My code is
void remove(int index)
{
if (head != NULL)
{
Node *current = get_node(index);
Node *prev = get_node(index - 1);
Node *next = get_node(index + 1);
prev->next = current->next;
delete current;
}
}
however, I am facing this error message
libc++abi.dylib: terminating with uncaught exception of type
std::range_error: IndexError: Index out of range
Abort trap: 6
I am guessing the problem is the pointers, but I am not sure why this is not working. Anyone who can help?
I think you can handle corner cases like this:
#include <iostream>
using namespace std;
struct Node {
Node(int val) {
this->val = val;
}
struct Node * next;
int val;
};
class LinkedList {
public:
Node* head;
LinkedList() {
head = new Node(1);
Node * n1 = new Node(2);
head->next = n1;
Node * n2 = new Node(3);
n1->next = n2;
}
void remove(int index) {
if (head == NULL) {
return;
}
int pos = 0;
Node * cur = head;
Node *prev = NULL;
while (cur != NULL) {
if (pos == index) {
break;
}
pos++;
prev = cur;
cur = cur->next;
}
if (prev == NULL) {
head = head->next;
}
else {
prev->next = cur->next;
}
delete cur;
}
};
void print(Node * head){
cout << "Current linked list:\n";
while(head != NULL) {
cout << head->val << endl;
head = head->next;
}
cout << endl;
}
int main() {
LinkedList * list = new LinkedList();
print(list->head);
list->remove(0);
print(list->head);
list->remove(1);
print(list->head);
list->remove(0);
print(list->head);
}

Why is this if statement triggered in this C++ code?

This code is supposed to reverse a linked list. The following code returns an empty linked list even when provided with a non empty list.
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* curr, *prev, *next;
if (head == NULL)
{
return head;
}
curr = head;
prev = NULL;
while (curr != NULL)
{
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
};
While this code strangely works where I added a cout statement just to check if the else was triggered.
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* curr, *prev, *next;
if (head == NULL)
{
cout << "Triggered";
return head;
}
curr = head;
prev = NULL;
while (curr != NULL)
{
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
};
Can someone please explain why this is happening?
Pretty simple, you have to initialize the pointers, else it leads to unexpected behavior that includes not showing it at all or just showing it if an initialized cout is triggered - but it doesn't have to do anything and that's up to your compiler implementation.
//cpp17
listNode* curr{}, *prev{}, *next{};
//before
listNode* curr = nullptr, *prev = nullptr, *next = nullptr;
It is still not in the reverse order as you intended to do.
class Solution {
public:
ListNode* reverseList(ListNode* head) {
listNode* curr{}, *prev{}, *next{};
//ListNode* curr, *prev, *next;
if (head == NULL)
{
return head;
}
curr = head;
prev = NULL;
while (next != NULL)
{
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
};
cheers :)
Like mentioned before I found time to write a solution for an other approach of solving your problem to reverse a linked list via class. For a better understanding for beginners I skipped the rule of three/five and initialized the list in the main function and not via constructor in the class:
#include <iostream>
class listElement
{
std::string data;
listElement* next;
listElement* last;
public:
void setData(std::string);
void append(std::string);
void displayElements();
void reverseDisplayElements(listElement*);
void freeMemory();
listElement* reverseList(listElement*);
};
void listElement::setData(std::string newData)
{
last = this;
data = newData;
next = nullptr;
}
void listElement::append(std::string newData)
{
// Double linked list
// last->next = new listElement();
// last->next->data = newData;
// last->next->next = nullptr;
// last = last->next;
// Singly linked list
//has next the value nullptr?
//If yes, next pointer
if (next == nullptr)
{
next = new listElement();
next->data = newData;
next->next = nullptr;
}
//else the method again
else
next->append(newData);
}
listElement* listElement::reverseList(listElement* head)
{
//return if no element in list
if(head == nullptr)
return nullptr;
//initialize temp
listElement* temp{};
while(head != nullptr){
listElement* next = head->next;
head->next = temp;
temp = head;
head = next;
}
return temp;
}
void listElement::displayElements()
{
//cout the first entry
std::cout << data << std::endl;
//if the end is not reached, call method next again
if (next != nullptr)
next->displayElements();
}
void listElement::reverseDisplayElements(listElement*head)
{
//recursiv from the last to the list beginning - stop
listElement *temp = head;
if(temp != nullptr)
{
if(temp->next != nullptr)
{
reverseDisplayElements(temp->next);
}
std::cout << temp->data << std::endl;
}
}
void listElement::freeMemory()
{
//If the end is not reached, call the method again
if (next != nullptr)
{
next->freeMemory();
delete(next);
}
}
int main ()
{
//Pointer to the Beginning of the list
listElement* linkedList;
//Creating the first element
linkedList = new listElement();
//Write data in the first element
linkedList->setData("Element 1");
//add more elements
linkedList->append("Element 2");
linkedList->append("Element 3");
linkedList->append("Element 4");
//display list
linkedList->displayElements();
//space divider
std::cout << "\nPrint in reverse order:" << std::endl;
//display list in reverse order
//pass list beginning as stop point
linkedList->reverseDisplayElements(linkedList);
std::cout << std::endl;
linkedList->displayElements();
std::cout << "\nReverse elements:" << std::endl;
linkedList = linkedList->reverseList(linkedList);
linkedList->displayElements();
std::cout << std::endl;
//destruct the list and free memory
linkedList->freeMemory();
delete(linkedList);
return 0;
}
Btw. there are many different solutions for that task.

(C++)Process returned -1073741819 (0xC0000005) when working with a linked list, but the algorithm works

The goal of this program is to remove any elements from the list that are greater than the following element. I've managed to make this program perform this task, however it crashes right after doing so and does not print the list afterwards, outputting an 0xC0000005 error code.
#include <iostream>
using namespace std;
class List{
struct node{
int data;
node* next;
};
typedef struct node* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
List()
{
head=NULL;
curr=NULL;
temp=NULL;
}
void AddNode(int addData)
{
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if(head != NULL) {
curr = head;
while(curr->next != NULL) {
curr = curr->next;
}
curr->next = n;
}
else
{
head = n;
}
};
void DeleteNode(int delData)
{
nodePtr delPtr = NULL;
temp = head;
curr = head;
while(curr != NULL && curr->data != delData) {
temp = curr;
curr = curr->next;
}
if(curr == NULL) {
cout << delData << " is not in the list" << endl;
delete delPtr;
}
else {
delPtr = curr;
curr = curr->next;
temp->next = curr;
if(delPtr == head) {
head = head->next;
temp = NULL;
}
delete delPtr;
cout << delData << " was removed from the list" << endl;
}
};
void PrintList()
{ cout << "List: " << endl;
curr = head;
while (curr != NULL) {
cout << curr->data << endl;
curr = curr->next;
}
}
void toss()
{
curr = head;
while (curr != NULL) {
if(curr->data>curr->next->data){
DeleteNode(curr->data);
curr = head;
}
else curr = curr->next;
if(curr == NULL) break;
}
}
};
int main() {
List list;
int i;
cout << "Input list values, stop input by inputting 0: " << endl;
cin >> i;
while(i != 0){
list.AddNode(i);
cin >> i; // 18 9 3 4 0
}
list.PrintList(); // 18 9 3 4
list.toss(); // tosses 18 and 9
list.PrintList(); // should output 3 4
};
This is the test example from the comments at the bottom of the code, it shows that the correct elements are removed, but doesn't print out the list the second time.
Input list values, stop input by inputting 0:
18
9
3
4
0
List:
18
9
3
4
18 was removed from the list
9 was removed from the list
Process returned -1073741819 (0xC0000005) execution time : 6.699 s
Press any key to continue.
Any input or help on this problem would be greatly appreciated, thanks!
When it reaches the last node in the list, aka curr->next equals null you are trying to access curr->next->data but next is null. Change your if statement to this:
while (curr != NULL) {
if(curr->next != NULL && curr->data > curr->next->data){
DeleteNode(curr->data);
curr = head;
}
else curr = curr->next;
if(curr == NULL) break;
}
or something equivalent. You can also check for this in the while loop's condition.
So basically you have to ensure that curr->next is not NULL before you access curr->next->data

linked list insertion, pointer confusion

I've looked around the forums but cant seem to find an answer to this very general question. The class below is a basic singly linked list with pushBack written the standard way.
class linkedList {
private:
typedef struct node {
int data;
struct node *next;
node(int d):data(d), next(NULL){}
}*nodePtr;
nodePtr head, temp, curr;
public:
linkedList():head(NULL), temp(NULL), curr(NULL){}
void pushBack(int d) {
temp = new node(d);
curr = head;
if (curr != NULL) {
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = temp;
} else head = temp;
}
void printAll() {
curr = head;
cout << "list:" << endl;
while (curr) {
cout << curr->data << " ";
curr = curr->next;
}
cout << endl;
}
};
but why cant my pushBack function be written like this?
void pushBack(int d) {
temp = new node(d);
curr = head;
while (curr != NULL) {
curr = curr->next;
}
curr = temp;
}
It should iterate through the list until curr == NULL and then set curr = temp. If the list is empty then it doesnt enter the loop and head will be set to the new node by setting temp to curr (which its self is set to head).
The logic makes perfect sense to me so it must be something else I'm missing.
Thank you for the help!
your function would fail for the first insertion or pushback, i.e, when the head pointer is null to begin with. when you assign head to curr like this:
curr = head;
curr now points to head and not vice versa .When curr is then assigned temp( i.e. when the first node isnserted into this linked list) , you have only reassigned the pointer curr with the location held by temp. Now all you have is a pointer curr pointing to the same location as temp, both of which pointers are not connected to head pointer at all!
a modified version of your code that would work is:
void pushBack(int d)
{
temp = new node(d);
curr = head;
if(curr!=NULL)
{
while (curr != NULL)
{
curr = curr->next;
}
curr = temp;
}
else head=temp;
}

Sorted queue linked list c++

I need to make a queue linked list in which the first node always has the smallest value , so it needs to be sorted , I have written this code :
#include <iostream>
using namespace std;
struct Node
{
int key;
Node *link;
};
class qlinkedlist
{
private:
Node *head;
Node *tail;
Node *curr;
Node *prev;
int count;
public:
void Enqueue(int value)
{
Node *newnode = new Node;
newnode -> key = value;
newnode -> link = NULL;
if(head==NULL)
{
head=tail=newnode;
count++;
}
else if(newnode->key < head->key)
{
newnode -> link = head;
head = newnode;
count++;
}
else
{
prev=head;
curr=head->link;
while(curr != NULL)
{
if(newnode->key < curr->key)
{
prev->link = newnode;
newnode->link = curr;
count++;
}
else
{
prev = curr;
curr = curr ->link;
}
}
}
}
void Dequeue()
{
if(head==NULL)
{
cout<< "Queue is empty" << endl;
}
else
{
curr = head;
head = head -> link;
delete curr;
count--;
}
}
void print()
{
curr = head;
while (curr!=NULL)
{
cout << curr -> key << endl;
curr = curr -> link;
}
}
};
void main()
{
qlinkedlist obj;
obj.Enqueue(5);
obj.Enqueue(4);
obj.Enqueue(3);
obj.Enqueue(2);
obj.Enqueue(1);
obj.print();
}
problem is it works only if I add nodes in the above order , for example if I try to add the 3 then 2 then 5 it does not work , what's wrong with the code ?
Thank you
Because if you try to add an element that is bigger than everything you have in the list, it will never pass your only condition to add a node: if(newnode->key < curr->key). Try this instead:
while(curr != NULL && newnode->key > curr->key)
{
prev = curr;
curr = curr ->link;
}
prev->link = newnode;
newnode->link = curr;
count++;
This way, you go through the linked list until you find the right spot, then add the new node even if you get to the end (curr==NULL).