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;
}
Related
I tried to get output after call insertNodeToEnd and displayNode. Bu I did not get any output. What is problem here?
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
void displayNode(Node* head ){
while(head!=NULL){//starting pointimiz NULL olana kadar döndür
cout<<head->data<<endl; //NULL olana kadar her Node'un data'sını yazdı
head = head->next;//ilerle
}
}
void insertNodeToEnd(Node*curr , int data){
while(curr->next !=NULL){
curr = curr->next;
}
curr ->next ->data = data;
curr ->next->next = NULL;
}
Node* head; //başlangıc node'unun adresini tuttuk
int main(){
Node* Head = new Node; //bir node oluşturduk
Head -> next = NULL;
Head -> data = 500; //oluşan node'un datasını oluşturduk
Node *iter = Head; //linked list içerisinde dolşacak iterator
//bu iterator'u head olarak tuttuk(artık döngüde iter'i başlangıç olarak kullanacağız)
int i = 0;
for(i = 0 ; i<5 ; i++){
insertNodeToEnd(iter,i*10);
}
displayNode(Head);
}
I tried to get output after call insertNodeToEnd and displayNode. Bu I did not get any output. What is problem here?
The problem is your insertNodeToEnd() is implemented all wrong. It is not creating a new Node, it is accessing curr->next when it is not pointing at a valid node, and it is not taking into account the possibility of head being NULL when the list is empty.
Try something more like this instead:
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
void displayNodes(Node* head){
while (head != NULL){
cout << head->data << endl;
head = head->next;
}
}
void insertNodeToEnd(Node* &head, int data){
Node *newNode = new Node;
newNode->data = data;
newNode->next = NULL;
if (head == NULL) {
head = newNode;
} else {
Node *curr = head;
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = newNode;
}
}
/* alternatively:
void insertNodeToEnd(Node* &head, int data) {
Node **curr = &head;
while (*curr != NULL) {
curr = &((*curr)->next);
}
*curr = new Node;
(*curr)->data = data;
(*curr)->next = NULL;
}
*/
void freeNodes(Node* head){
while (head != NULL){
Node *next = head->next;
delete head;
head = next;
}
}
int main(){
Node* head = NULL;
insertNodeToEnd(head, 500);
for(int i = 0; i < 5; ++i){
insertNodeToEnd(head, i*10);
}
displayNodes(head);
freeNodes(head);
}
Online Demo
That being said, consider using the standard std::list container instead, eg:
#include <iostream>
#include <list>
using namespace std;
void displayNodes(const list<int> &lst){
for (int elem : lst){
cout << elem << endl;
}
}
int main(){
list<int> lst;
lst.push_back(500);
for(int i = 0; i < 5; ++i){
lst.push_back(i*10);
}
displayNodes(lst);
}
Online Demo
I am learning DSA, and was trying to implement linked list but the insertion function that i wrote is not
working in a for or while loop, its not the same when i call that function outside the loop, it works that way. I am not able to figure it out, please someone help me.
#include <iostream>
class Node {
public:
int data;
Node *next;
Node(int &num) {
this->data = num;
next = NULL;
}
};
class LinkedList {
Node *head = NULL;
public:
void insert(int num) {
Node *tmp;
if (head == NULL) {
head = new Node(num);
tmp = head;
} else {
tmp->next = new Node(num);
tmp = tmp->next;
}
}
void printList() {
Node *tmp = head;
while (tmp) {
std::cout << tmp->data << " ";
tmp = tmp->next;
}
std::cout << std::endl;
}
void reverseList() {
Node *curr = head, *prev = NULL, *nextNode;
while (curr) {
nextNode = curr->next;
curr->next = prev;
prev = curr;
curr = nextNode;
}
head = prev;
}
};
int main() {
LinkedList list1;
// This is not working
int num;
while (num != -1) {
std::cin >> num;
list1.insert(num);
}
// This is working
// list1.insert(1);
// list1.insert(2);
// list1.insert(3);
// list1.insert(4);
// list1.insert(5);
list1.printList();
list1.reverseList();
list1.printList();
return 0;
}
I expect this after insertion
Edit:
although #Roberto Montalti solved this for me, but before that I tried passing incrementing value using a for loop which worked but as soon as I pull that cin out it crashes. can someone tell me what's happening under the hood?
for (int i = 1; i <= 10; i++)
{
list1.insert(i);
}
When inserting the nth item (1st excluded) tmp is a null pointer, i don't understand what you are doing there, you are assigning to next of some memory then you make that pointer point to another location, losing the pointer next you assigned before, you must keep track of the last item if you want optimal insertion. This way you are only assigning to some *tmp then going out of scope loses all your data... The best way is to just keep a pointer to the last inserted item, no need to use *tmp.
class LinkedList
{
Node *head = NULL;
Node *tail = NULL;
public:
void insert(int num)
{
if (head == NULL)
{
head = new Node(num);
tail = head;
}
else
{
tail->next = new Node(num);
tail = tail->next;
}
}
...
}
You need to loop until you reach the end of the list and then add the new node after that. Like this.
void insert(int num) {
Node *tmp = head;
if (head == NULL) {
head = new Node(num);
}
else {
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = new Node(num);
}
}
first of all you need to define a node for each of the tail and head of the list as follows
Node *h;
Node *t;
you may also separate the Node from the LinkedList class so you can modify easily
class Node{
public:
int data;
Node *next;
Node(int data, Node* next);
~Node();
};
Node::Node(int data, Node* next)
{
this->data= data;
this->next= next;
}
Node::~Node(){}
}
after that you can try to add these functions to your LinkedList class
so it can deal with other special cases such empty list or full, etc..
void addToHead(int data){
Node *x = new Node(data,h);
h=x;
if(t==NULL){
t=x;
}
void addToTail(int data){
Node *x = new Node(data,NULL);
if(isEmpty()){
h=t=x;
}
else
{
t->next=x;
t=x;
}
}
now for the insert function try this after you implemented the Node class and the other functions,
void insert(int v){
if(h==nullptr){addToHead(v); return;}
if(h->data>=v) {addToHead(v);return;}
if(t->data<=v) {addToTail(v); return;}
// In this case there is at least two nodes
Node *k=h->next;
Node *p=h;
while(k != nullptr){
if(k->data >v){
Node *z =new Node(v,k);
p->next=z;
return;
}
p=k;
k=k->next;
}
}
the idea of making all of this is not lose the pointer when it goes through elements in the Linked List so you don't end up with a run time error.
I hope this can be useful to you.
There was an issue with your insert function.
Read about segmentation fault here https://www.geeksforgeeks.org/core-dump-segmentation-fault-c-cpp/#:~:text=Core%20Dump%2FSegmentation%20fault%20is,is%20known%20as%20core%20dump.
for a quick workaround you can use this
using namespace std;
#include <iostream>
class Node
{
public:
int data;
Node *next;
Node(int num)
{
this->data = num;
next = NULL;
}
};
class LinkedList
{
Node *head = NULL;
public:
void insert(int num)
{
Node *tmp= new Node(num);
tmp->next=head;
head=tmp;
}
void printList()
{
Node *tmp = head;
while (tmp)
{
std::cout << tmp->data << " ";
tmp = tmp->next;
}
std::cout << std::endl;
}
void reverseList()
{
Node *curr = head, *prev = NULL, *nextNode;
while (curr)
{
nextNode = curr->next;
curr->next = prev;
prev = curr;
curr = nextNode;
}
head = prev;
}
};
int main()
{
LinkedList list1;
// This is not working
int num,i=0,n;
cout<<"Type the value of n";
cin>>n;
while (i<n)
{
cin >> num;
cout<<num<<" "<<&num<<endl;
list1.insert(num);
i++;
}
list1.printList();
list1.reverseList();
list1.printList();
return 0;
}
The below code is for merge sorting a linked list. Its giving out a segmentation fault. I really dont know how to deal with the above. All I could find was that I was trying to access a restricted part of the memory, the only place I think i could've gone wrong is re combining the two linked lists after splitting and sorting them under the split function body. I'd appreciate if I could get some guidance on how to deal with segmentation faults from here on & how to rectify them.
//Segmentation fault
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int data)
{
this->data = data;
next = NULL;
}
};
void print(Node *head)
{
Node *temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
}
Node *insert()
{
int data;
cin >> data;
Node *head = NULL;
Node *tail = NULL;
while (data != -1)
{
Node *n = new Node(data);
if (head == NULL)
{
head = n;
tail = n;
}
else
{
tail->next = n;
tail = tail->next;
}
cin >> data;
}
return head;
}
Node *sortedMerge(Node *h1, Node *h2)
{
// Node *fHead = NULL;
// Node *fTail = NULL;
if (!h1)
{
return h2;
}
if (!h2)
{
return h1;
}
if (h1->data < h2->data)
{
h1->next = sortedMerge(h1->next, h2);
return h1;
}
else
{
h2->next = sortedMerge(h1, h2->next);
return h2;
}
}
void split(Node *head, Node *h1, Node *h2)
{
Node *slow = head;
Node *fast = head->next;
while (fast != NULL)
{
fast = fast->next;
if (fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
}
h1 = head;
h2 = slow->next;
slow->next = NULL;
}
void mergeSort_LL(Node *head)
{
Node *temp = head;
Node *h1;
Node *h2;
if ((temp == NULL) || (temp->next == NULL))
{
return;
}
split(temp, h1, h2);
mergeSort_LL(h1);
mergeSort_LL(h2);
head = sortedMerge(h1, h2);
}
int main()
{
Node *head = insert();
print(head);
cout << endl;
mergeSort_LL(head);
cout << "Sorted List is : " << endl;
print(head);
return 0;
}
Your call to split will not make h1 or h2 get a value. Arguments are passed by value. Since you evidently need h1 and h2 to get a different value from that split call, you should pass their addresses:
split(temp, &h1, &h2)
The function itself should therefore accept these addresses instead of the node pointers themselves:
void split(Node *head, Node **h1, Node **h2) {
// ...
*h1 = head;
*h2 = slow->next;
// ...
}
I catched segfault when run this code and can`t understand why.
If firstly i use one time push(&head,3); then segfault is not catched, but it works bad for true
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *next;
};
void push(Node **head,int data)
{
Node *tmp = new Node;
tmp->data = data;
tmp->next = (*head);
(*head) = tmp;
}
Node *getLast(Node *head)
{
if(head == nullptr)
{
return nullptr;
}
while(head->next)
{
head=head->next;
}
return head;
}
void show(const Node *head)
{
while(head!=nullptr)
{
cout << head->data << endl;
head = head->next;
}
}
void pushBack(Node *head,int data)
{
Node *last = getLast(head);
Node *tmp = new Node;
tmp->data = data;
tmp->next = nullptr;
last->next = tmp;
}
int main() {
Node *head=nullptr;
**//push(&head,2); /////if I use this then it works! but it not right.**
pushBack(head,10);
pushBack(head,2);
pushBack(head,3);
show(head);
return 0;
}
I tried to google it but it helpless.
How to solve this problem?
If the linked list is empty you have to modify head which requires to pass the reference of head. This should work:
void pushBack(Node **head,int data)
{
Node *last = getLast(*head);
Node *tmp = new Node;
tmp->data = data;
tmp->next = nullptr;
if(last == nullptr)
{
*head = tmp;
}
else
{
last->next = tmp;
}
}
int main() {
Node *head=nullptr;
pushBack(&head,10);
pushBack(&head,2);
pushBack(&head,3);
show(head);
return 0;
}
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
temp = head;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
}
temp = prev;
temp = temp->next;
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.DelNum(3);
list.PrintList();
return 0;
}
What is wrong with my DelNum function? When I run the program nothing pops up. Doesn't matter what number I put in.
As mss pointed out the problem is in your DelNum() function where you assign temp = prev;. In your initialization you defined that node* prev = NULL; So, prev = NULL at the point when you assigned it to temp which caused segmentation fault when you try to use it like temp = temp->next;.
Two main problems are there in DelNum function:
first, when you are in while loop
, you should assign
prev = temp;
second, when you have found your target element, after deleting it you have to break out of the loop, which isn't done in your code
below is your corrected code( also correction of some other corner case in DelNum function ):
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
cout<<num<<" is added \n";
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
if(head==NULL)//empty
{
cout<<"empty linked list, can't be deleted\n";
return;
}
if(head->next==NULL)//means only one element is left
{
if(head->data==num)
{
node * fordelete=head;
head=NULL;
cout<<num<<"is deleted\n";
delete(fordelete);
}
else
{
cout<<"not found , can't be deleted\n";
}
return;
}
temp = head; // when more than one element are there
prev = temp;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
cout<<num<<" is deleted\n";
break;
}
prev= temp;
temp = temp->next;
}
if(temp==NULL)
{
cout<<"not found, can't be deleted\n";
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.PrintList();
list.DelNum(3);
list.DelNum(7);
list.PrintList();
return 0;
}
I hope it will help you.