Singly Linked List inserting and deleting value in order - c++

I was tasked with creating functions to add and delete nodes in a linked list given input data as an int and the char for with function to call. I'm not sure what I'm doing wrong. The only error I was given was: Exited with return code -11 (SIGSEGV). And a compiler method: main.cpp: In function ‘void listInsertValue(ListNode*&, ListNode*&, int)’:
main.cpp:111:23: warning: ‘toGoAfter’ may be used uninitialized in this function [-Wmaybe-uninitialized]
111 | toGoAfter->next = head;
Any help is appreciated. Thanks!
#include <iostream>
using namespace std;
struct ListNode
{
int data;
ListNode* next;
};
void listRemoveAfter(ListNode*&, ListNode*&, ListNode*);
void listPrepend(ListNode*&, ListNode*&, ListNode*&);
void listDeleteValue(ListNode*&, ListNode*&, int);
void listInsertValue(ListNode*&, ListNode*&, int);
void listInsertAfter(ListNode*&, ListNode*&, ListNode*, ListNode*);
int main()
{
ListNode *head = nullptr, *tail = nullptr;
ListNode *temp;
char choice;
int val;
//Write a main like you did in the previous lab
char command;
int number;
cin >> command;
while(command != 'Q')
{
if(command == 'I')
{
cin >> number;
listInsertValue(head,tail,number);
}
else
{
cin >> number;
listDeleteValue(head,tail,number);
}
cin >> command;
}
ListNode* current;
current = head;
while (current != nullptr)
{
cout << current->data << " ";
current = current->next;
}
cout << endl;
return 0;
}
//From previous lab - already complete
void listPrepend(ListNode*& h, ListNode*& t, ListNode*& n)
{
if (h == nullptr)
{
h = n;
t = n;
}
else
{
n->next = h;
h = n;
}
}
//From book, write yourself using the book code in 17.6 as a starting point
void listInsertAfter(ListNode*&head, ListNode*&tail, ListNode* curNode, ListNode* newNode)
{
if (head->next == nullptr)
{
head= newNode;
tail = newNode;
}
else if (curNode->next == tail)
{
tail->next = newNode;
tail = newNode;
}
else
{
newNode->next = curNode;
curNode->next = newNode;
}
}
//This function is mostly written, but you will need to add some code near the TODOs to complete the algorithm from the slides
void listInsertValue(ListNode*& head, ListNode*& tail, int val)
{
ListNode* toGoAfter, *newNode;
//TODO - create a new ListNode (newNode) with a data value of val (3 lines of code)
newNode = new ListNode;
newNode->data = val;
newNode->next = nullptr;
//TODO - check whether the list is empty in the if condition
if (head == nullptr)
{
listInsertAfter(head, tail, nullptr, newNode);
}
//TODO - use the else if to check whether the the value passed in is smaller than the value in the head
else if (head->data > val) //need to add to beginning of the list
{
listPrepend(head, tail, newNode);
}
else //need to add somewhere else in the list
{
//TODO - set toGoAfter to point to the head
toGoAfter->next = head;
//loop to find the location to insert the value
while (toGoAfter->next != nullptr && toGoAfter->next->data < val)
{
//TODO - set toGoAfter to point to the node after toGoAfter, like is done in traversals
toGoAfter = toGoAfter->next;
}
//We have found the location, so we can insert
listInsertAfter(head, tail, toGoAfter, newNode);
}
}
//modify
void listDeleteValue(ListNode* &head, ListNode*& tail, int val)
{
ListNode *temp;
//TODO - check if list is not empty in if condition
if (head->next == nullptr)
{
// TODO - check if value of head matches val passed in
if (head->data == val)
listRemoveAfter(head, tail, nullptr);
}
else
{
//loop searches for value to delete in node following temp
//TODO - set temp to point to the head
temp->next = head;
while (temp->next != nullptr && temp->next->data != val)
{
//TODO - set temp to point to the node after temp, like is done in traversals
temp = temp->next;
}
//TODO - make sure a node exists after temp, meaning the value to delete was found
if (temp->next != nullptr)
listRemoveAfter(head, tail, temp);
}
}
//From book, write yourself using the book code in 17.7 as a starting point
//Also add to the book's code, the code to delete nodes from memory
void listRemoveAfter(ListNode* & head, ListNode*& tail, ListNode* curNode)
{
ListNode *sucNode, *toDelete;
if (curNode->next == nullptr && head->next != nullptr)
{
sucNode = head->next;
head->next = sucNode;
if (sucNode->next == nullptr)
{ // Removed last item
tail->next = nullptr;
toDelete = head;
}
}
else if (curNode->next != nullptr)
{
sucNode = curNode->next->next;
curNode->next = sucNode;
if (sucNode-> next == nullptr)
{ // Removed tail
tail->next = curNode;
toDelete = curNode->next;
}
}
delete toDelete; //needed after the if/else if to remove the deleted node from memory
}

For most part you are not handling the case when there ia no element in the list. While inserting handle 4 use cases
Head==nullptr => head =newNode;
head->data > val
Tail->data < val
else case : insert in middle
Generic mistake: accessing ptr-> next, when ptr is nullptr
In general you want to use a debugger and any access to a memory 0x0 (nullptr) will start resolving your issues. ie head is 0x0 and you are doing operationa like head->data ==val

Related

Reversing LinkedList result in wrong links by recursion

I wrote the following code to reverse a linked list recursively for my homework. However, It's not connecting the links properly. Can please someone tell me what's wrong in the following reverse function? I have tried GDB as well. But, could not figure out what's wrong?
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
explicit Node(int data)
{
this->data = data;
next = nullptr;
}
};
void pushBack(Node * &head, Node * &tail, int data)
{
if(head == nullptr)
{
head = new Node(data);
tail = head;
}
else
{
tail->next = new Node(data);
tail = tail->next;
}
}
void printList(Node *head)
{
if(head == nullptr)
return;
cout << head->data << " ";
printList(head->next);
}
void reverseListRecursive(Node * &head)
{
if(head->next == nullptr)
{
return;
}
reverseListRecursive(head->next);
head->next->next = head;
head->next = nullptr;
}
int main()
{
int cap;
cin >> cap;
Node *head = nullptr, *tail = nullptr;
for(int i = 0; i < cap; ++i)
{
int element;
cin >> element;
pushBack(head, tail, element);
}
reverseListRecursive(head);
printList(head);
return 0;
}
Head is being passed by reference and also the infinite recursion is also not there.
The problem is that the head pointer needs to point to the last node of the linked list. Following code fixes the problem.
void reverseListRecursive(Node * &head, Node *temp = nullptr)
{
if(temp == nullptr)
temp = head;
if(temp->next == nullptr)
{
head = temp;
return;
}
reverseListRecursive(head, temp->next);
temp->next->next = temp;
temp->next = nullptr;
}

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.

Unable to create or return Reversed Linked list

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

Linked list head pointer not getting updated when called by reference

I have written two functions to insert nodes in a Linked List. While one function (insertNth) updates the head pointer, the second one (sortedInsert) does not update the head pointer across function calls. The push function is taking a reference to the head pointer.
struct node
{
int data;
node *next;
};
void printList(node *head)
{
node *current = head;
while(current!=NULL)
{
cout<<current->data<<" ";
current = current->next;
}
}
void push(node* &head, int data)
{
node *newNode = new node();
newNode->data = data;
newNode->next = head;
head = newNode;
}
void insertNth(node *&head, int index, int val)
{
node *current = head;
int cnt = 0;
while(current!=NULL)
{
if(cnt == index)
{
if(cnt==0)
{
push(head, val);
}
else
{
push(current->next, val);
}
}
current=current->next;
cnt++;
}
}
void sortedInsert(node *head, int val)
{
node *current = head;
if(head != NULL && val < head->data)
{
node *newNode = new node();
push(head,val);
return;
}
while(current!=NULL)
{
if(current->data < val && current->next->data > val)
{
push(current->next, val);
return;
}
current = current->next;
}
}
int main()
{
node *head;
push(head, 3);
cout<<"\n";
printList(head);
cout<<"\nInsertNth: ";
insertNth(head,0, 2);
printList(head);
cout<<"\nsortedInsert: ";
sortedInsert(head, 1);
printList(head);
return 0;
}
I'm getting following as output:
3
InsertNth: 2 3
sortedInsert: 2 3
Why is the third line not printing 1 2 3?
//
Update
//
The correct SortedInsert is as follows:
void sortedInsert(node *&head, node *newNode)
{
node *current = head;
if(head == NULL || newNode->data < head->data)
{
newNode->next = head;
head = newNode;
return;
}
while(current!=NULL && current->next != NULL)
{
if(current->data < newNode->data && current->next->data > newNode->data)
{
newNode->next = current->next;
current->next = newNode;
return;
}
current = current->next;
}
if(current->next == NULL)
{
current->next = newNode;
newNode->next = NULL;
}
}
A sample was requested. Note that I did it as a template, but you could skip the template business and instead of a T* you can use struct node *. It's not general purpose, but might be easier to understand.
template <class T>
class MyLinkedList {
class Entry {
public:
Entry * previous;
Entry * next;
T * node;
}
Entry * head;
Entry * tail;
void push(T * nodeToPush) { pushBefore(head, nodeToPush); }
void insertNth(int whereToInsert, T * nodeToInsert) {
... find the nth Entry pointer
pushBefore(head, nodeToPush);
}
private:
void pushBefore(Entry *entry, T * nodeToPush) {
Entry *newEntry = new Entry();
newEntry->node = nodeToPush;
if (entry != NULL) {
newEntry->previous = entry->previous;
}
newEntry->next = entry;
entry->previous = newEntry;
if (head == entry) {
head = newEntry;
}
if (tail == NULL) {
tail = newEntry;
}
}
// Other methods as necessary, such as append, etc.
}
Other than passing in a pointer to the objects you're inserting into your linked list, at no point do you have to pass pointers around in a fashion where your methods are also performing side effects on those pointer. The class should know how to manage a class, and no weird passing of variables all over.
Performing side effects on your arguments should be done with GREAT caution. If you're passing an object to a method, then it's fair to manipulate the object. But I really don't like passing pointers and having methods modify the pointers themselves.
That IS going to lead to (at best) confusion.
Note: I did NOT test this code. It might not quite be perfect.

segmentation fault when I'm trying to print my list through my function

I know this is probably trivial to the c++ programmer, but I'm a noobie trying to figure this out. In my main, if I print my short list manually(cout << head->value etc) it works, but when I use my print function I get a segmentation fault. I've been trying to use a debugger, but I'm not very good at unix/c++ and I'm getting frustrated trying to figure this out.
#include <iostream>
using namespace std;
class ListNode
{
public:
int value;
ListNode* next;
};
void insertAtHead(ListNode** head, int value)
{
ListNode *newNode = new ListNode;
newNode->value = value;
if(head == NULL)
{
*head = newNode;
newNode->next = NULL;
}
else
{
newNode->next = *head;
*head = newNode;
}
}
void printList(ListNode* head)
{
while(head != NULL)
{
cout << head->value << "->";
head = head->next;
}
}
//inserts after the node with given value
void insertAfterNode(ListNode** head,ListNode** newNode, int value)
{
ListNode* current = *head;
while(current != NULL && (current->value != value))
{
//cout << "Im Here";
current = current->next;
cout << current->value;
}
(*newNode)->next = current->next;
current->next = *newNode;
}
int main()
{
ListNode *head;
insertAtHead(&head, 5);
insertAtHead(&head, 10);
ListNode* newNode = new ListNode;
newNode->value = 8;
newNode->next = NULL;
insertAfterNode(&head,&newNode, 5);
printList(head);
}
Check this modifications in your functions
void insertAtHead(ListNode** head, int value)
{
ListNode *newNode = new ListNode;
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
void printList(const ListNode* head)
{
while(head != NULL)
{
cout << head->value << "->";
head = head->next;
}
}
In insertAtHead you are pasing a double pointer, so comparison should be like this.
Added checking for whether *head is null before accessing. and if null adding new node as head
void insertAfterNode(ListNode** head,ListNode** newNode, int value)
{
ListNode* current = *head;
if (current != NULL)
{
while(current != NULL && (current->value != value))
{
//cout << "Im Here";
current = current->next;
cout << current->value;
}
(*newNode)->next = current->next;
current->next = *newNode;
}
else
{
*head = *newNode;
}
}
And in main intialise head before use
int main()
{
ListNode *head = NULL;
insertAtHead(&head, 5);
printList(head); // <== note: by-value, not by address or reference.
You need to check if the next value you are trying to access is not null like this :
void printList(ListNode* head)
{
if (head != NULL)
{
while(head->next != NULL)
{
cout << head->value << "->";
head = head->next;
}
}
}
Dude the first answer is correct
But i would like to make another correction
In your while loop in function insert after node
current!=NULL is incorrect because then your condition will be true if and only if the last node in the list matches the value of 5
Condition should be just while(current->value!=value)
by this you will reach the node having value 5