I am trying to create a single linked list but the above code is giving an error: segmentation fault core dumped. I am inserting elements 5,9,12 in the singlelinkedlist and displaying the list. First I create a node and then class singlelinkedlist with all the methods. I am still trying to learn basics.
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node* next;
Node()
{
}
Node(int element)
{
data = element;
next=NULL;
}
Node(int element, Node* link)
{
data = element;
next = link;
}
};
class SingleLinkedList
{
public:
Node* head;
int listsize = 0;
Node* curr;
bool isempty()
{
return head==NULL;
}
void Insert(int data)
{
Node* new_node = new Node(data);
if(isempty())
{
head = new_node;
listsize++;
return;
}
curr = head;
while(curr->next!=NULL)
{
curr->next=curr;
}
curr->next=new_node;
listsize++;
}
void display()
{
curr = head;
while(curr!=NULL)
{
cout<<curr->data<<"-->";
curr=curr->next;
}
}
};
int main()
{
SingleLinkedList l1;
l1.Insert(5);
l1.Insert(9);
l1.Insert(12);
l1.display();
}
Try to change:
while (curr->next != NULL)
{
curr->next = curr;
}
to:
while (curr->next != NULL)
{
curr = curr->next;
}
for you list traversal while doing node insertion to avoid infinite loop
The pointer head is not initialized. Its value is not garanteed to be nullptr. Your code is therefore UB, since the first insert in the list will invoke isempty(), which is using this uninitialised pointer.
When this is done, consider also Anon’s answer.
Related
ok, I created a linked list using the Node class and List class. But whenever I run it using the List object, it throws an exception when I return the head in the getHead() function in Node.cpp
these are the files that I created please if anyone could know why this exception is coming it would be a blessing
//**NODE.h**
#include<iostream>
using namespace std;
class Node{
private:
Node* head;
int data;
public:
Node();
Node(int); //insert data
void setHead(Node*);
Node* getHead();
void setData(int);
int getData();
void printData(Node*);
};
//**Node.cpp**
#include"Node.h"
Node::Node(){
//Node* head = new Node();
head = NULL;
data = 0;
}
Node::Node(int DATA){
//Node* head = new Node();
head = nullptr;
data = DATA;
}
int Node::getData(){ //DATA SETTER
return this->data;
}
void Node::setData(int DATA){ //DATA GETTER
this->data = DATA;
}
Node* Node::getHead(){
return head;
}
void Node::setHead(Node* NextAddress){
this->head = NextAddress;
}
void Node::printData(Node* node){
while(node != nullptr){
cout<< this->data <<"\n";
node = node->head;
}
}
//**List.h**
#include"Node.h"
class List : public Node{
private:
Node* head;
Node* current;
Node* prevcurrent;
public:
List();
//void setList(int);
void insertAtBack(Node* , int);
void insertAtFront(Node* , int);
bool search(int);
void print();
~List();
};
//**List.cpp**
#include"List.h"
List::List(){
head=nullptr;
current=nullptr;
prevcurrent=nullptr;
}
void List::insertAtBack(Node* head , int Data){
Node* newNode = new Node();
newNode->setData(Data);
newNode->setHead(head); //sets the address of the next node into the newly added node
head = newNode;
}
void List::insertAtFront(Node* head, int Data) {
Node* temp = new Node();
}
bool List::search(int num){
Node* temp = head;
while (temp->getHead()!=nullptr)
{
if (temp->getData() == num)
{
return true;
}
temp->setHead(temp->getHead()); //itereates the adress in the emp node to store the address of the next node fro the while loop
}
}
void List::print(){
Node* temp=head;
while (temp->getHead() != nullptr)
{
cout<<temp->getData()<<" ";
}
}
List::~List() {
Node* temp = head;
while (temp->getHead() != nullptr)
{
Node* temp2 = temp;
temp = temp->getHead();
delete temp2;
}
}
//**main.cpp**
#include"List.h"
int main(){
// cout<<"running\n";
// Node box(5); this works
// cout<<box.getData();
List obj;
Node node; //this will throw an exception
obj.insertAtBack(&node,5);
obj.print();
}
Exception is thrown due to print:
void List::print() {
Node *temp = head;
while (temp->getHead() != nullptr) {
cout << temp->getData() << " ";
}
}
Here, a check is missing if temp (or equally head) is a nullptr before you dereference it in temp->getHead()
Same on List::~List
class Node{
public:
int data;
Node* next;
Node(int d){
data = d;
next = NULL;
}
~Node(){
delete next;
}
};
class List{
public:
Node* head;
Node* tail;
List(){
head = NULL;
tail = NULL;
}
~List(){
delete head;
}
void push_back(int data){
Node* n = new Node(data);
if(head == NULL){
head = tail = n;
}else{
tail->next = n;
tail = n;
}
}
void print(){
Node* temp = head;
while(temp != NULL){
cout<<temp->data<<" ";
temp = temp->next;
}
}
void deleteNode(int d){
Node* curr = head;
Node* prev = NULL;
while(curr != NULL){
if(curr->data == d){
if(prev == NULL){
head = head->next;
delete curr;
break;
}else{
prev->next = curr->next;
curr->next = NULL;
delete curr;
break;
}
}
prev = curr;
curr = curr->next;
}
}
};
int main(){
List l;
l.push_back(1);
l.push_back(2);
l.push_back(3);
l.push_back(4);
l.push_back(5);
l.deleteNode(1);
l.print();
}
If I delete 1 from 1->2->3->4->5
Expected Output: 2->3->4->5
Output: free(): double free detected in tcache 2;
Reason: Destructor in Node Class. If I remove it is working fine.
Doubt : If I remove destructor in Node class in Node class then how can I free up memory. And can anyone also explain how destructors are working in both Node and List class.
Can someone please help me with this, or can provide alternative solution.
Thank You!!!
~Node(){ delete next; } makes it hard to delete a single node from that list. It'll delete all nodes after it too.
I suggest that the individual Nodes do not delete following Nodes:
class Node {
public:
int data;
Node* next;
Node(int d) : // colon starts the member initializer list
data(d), next(nullptr)
{
// the body of the constructor can now be empty
}
// No user-defined destructor needed here
};
Instead, delete all Nodes in the destructor of List:
~List() {
for(Node* next; head; head = next) {
next = head->next;
delete head;
}
}
Unrelated to the problem at hand. These are just suggestions:
You could make the constructor of Node a little more versatile so it's possible to provide the next Node already at construction:
class Node {
public:
int data;
Node* next;
// `nullptr` below is a default argument that will be used if the
// user of this class does not provide a second argument
Node(int d, Node* n = nullptr) :
data(d), next(n)
{}
};
This could be used in a List member function called push_front:
void push_front(int data) {
head = new Node(data, head);
if(!tail) tail = head;
}
Unrelated to that, you could make push_back a little clearer without even changing the current Node at all:
void push_back(int data) {
Node* n = new Node(data);
if(tail) tail->next = n;
else head = n;
tail = n;
}
To follow up on my comments: Throw away both your Node and List class, and actually use the language:
#include <forward_list>
#include <iostream>
int main(){
std::forward_list< int > l { 1, 2, 3, 4, 5 };
l.remove( 1 );
for ( auto & node : l )
{
std::cout << node << " ";
}
}
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;
}
I have given insert and a print function to insert data in a linked list and then print it.
But somehow it does not give any output and keeps running for a infinite time.
What is wrong?
Here is the code I have written. This is a simple program to create a linked list using loops and functions.
#include<iostream>
using namespace std;
struct node{
int data;
struct node* next;
};
struct node* head;
void insert(int data){
struct node* temphead=head;
if (temphead == NULL)
{
node* temp = new node();
temp->data=data;
temp->next=NULL;
while (temphead == NULL){
head==temp;
}
}
else if (temphead != NULL)
{
node* temp = new node();
temp->data=data;
temp->next=NULL;
while (temphead != NULL)
{
temphead->next= temp;
temphead=temphead->next;
}
}
}
void print(){
struct node* tempptr = head;
while (tempptr->next != NULL)
{
cout<<tempptr->data<<"_";
tempptr=tempptr->next;
}
}
int main(){
head=NULL;
insert(2);
insert(4);
insert(8);
insert(6);
//list - 2_4_8_6
print();
return 0;
}
There were few bugs in your code and also typos. Please read the comments marked with // CHANGE HERE for the description of the changes I did:
#include <iostream>
using namespace std;
struct node{
int data;
struct node* next;
};
struct node* head;
void insert(int data){
struct node* temphead = head;
if (temphead == nullptr)
{
node* temp = new node();
temp->data = data;
temp->next = nullptr;
// CHANGE HERE: removed unnecessary while loop
// Directly assign temp to head
head = temp;
}
else
{
node* temp = new node();
temp->data=data;
temp->next=nullptr;
// CHANGE HERE: check for temphead->next instead of temphead
while (temphead->next != nullptr)
{
// CHANGE HERE: remove unnecessary line: temphead->next= temp;
temphead=temphead->next;
}
// CHANGE HERE: assign temp to temphead->next (i.e. to last node)
temphead->next = temp;
}
}
void print(){
struct node* tempptr = head;
// CHANGE HERE: check for tempptr instead of tempptr->next
while (tempptr != nullptr)
{
cout<<tempptr->data<<"_";
tempptr=tempptr->next;
}
}
int main(){
head=nullptr;
insert(2);
insert(4);
insert(8);
insert(6);
//list - 2_4_8_6
print();
return 0;
}
NOTE: Your code uses new for dynamic memory allocation but doesn't use delete to de-allocate the memory when not required. If you want to avoid using new/delete, you can explore about smart pointers.
Could someone please help me identify the problem with the code below.
#include <iostream>
using namespace std;
struct node
{
int a,b;
struct node* next=NULL;
};
node* head=NULL;
void insert(int a,int b)
{
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
return;
}
node* cur=head;
while(cur!=NULL)
{
cur=cur->next;
}
cur=new node;
cur->a=a;
cur->b=b;
return;
}
void display()
{
node* cur=head;
while(cur!=NULL)
{
cout<<cur->a<<"\t"<<cur->b<<"\n";
cur=cur->next;
}
}
int main()
{
int i;
for(i=0;i<3;++i)
{
insert(i,i+1);
}
display();
//cout<<h->next->a;
return 0;
}
This is the output that I get:
0 1
It seems that I can only display the head node and none after gets inserted. If I try to access the next node after head, I get a segmentation fault. Why is that?
Your search code is:
node* cur=head;
while(cur!=NULL)
{
cur=cur->next;
}
cur=new node;
At the end of the loop, you've found the right place to add the new node, but you overwrite that with cur = new node; — so you need to use something more like:
node *new_node = new node;
new_node->a = a;
new_node->b = b;
new_node->next = nullptr;
cur->next = new_node;
Or, equivalently:
cur->next = new node;
cur->next->a = a;
cur->next->b = b;
cur->next->next = nullptr;
Even better, you'd create a constructor for the struct node class, such as:
node(int a_init = 0, int b_init = 0) : a(a_init), b(b_init), next(nullptr) { }
and then:
cur->next = new node(a, b);
would do the whole initialization job.
While inserting, update head->next to NULL (when head is NULL)
and curr->next to NULL (when some elements are already in the list)
respectively.
You are not linking head to curr. To link head and curr, you can
create another pointer instead to hold the new element, say new_ptr.
Keep curr such that curr->next=NULL, and then write
curr->next=new_ptr.
void insert(int a,int b)
{
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
head->next=NULL;
return;
}
node* cur=head,*new_ptr;
while(cur->next!=NULL)
{
cur=cur->next;
}
new_ptr=new node;
new_ptr->a=a;
new_ptr->b=b;
new_ptr->next=NULL;
curr->next=new_ptr;
return;
}
I found out the bug .While inserting , instead of sitting in a node and checking if it is null , look 1 node ahead and check if its null. Because if you don't , then the list will get broken and cpp allocates memory else where rather than to the pointer of the last list node's next branch.
Modified insert function :
void insert(int a,int b)
{
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
head->next=NULL;
return;
}
node* cur=head;
while(cur->next!=NULL)
{
//cout<<cur->a<<"\t"<<cur->b<<"\n";;
cur=cur->next;
}
cur->next=new node;
cur->next->a=a;
cur->next->b=b;
return;
}
At the time of creation of any node , the next pointer of that node becomes null as per the definition of your node.
struct node
{
int a,b;
struct node* next=NULL;
};
Now,after the creation of start node ,the next pointer of start node is NULL.And when u created your second node ,you didn't point the next node of your first node to the second node.Then how will you be able to reach to the second node if you do not have the pointer to the second node.
So the solution will be --
void insert(int a,int b)
{
node *temp;
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
temp=head;
return;
}
node* cur=head;
while(cur!=NULL)
{
cur=cur->next;
}
cur=new node;
temp->next=cur;
cur->a=a;
cur->b=b;
temp=cur;
return;
}