I am getting a segmentation fault for the code below when the program reaches addnode() function. So I don't know if there would be any issues elsewhere since the flow is not going forward
#include<iostream>
using namespace std;
struct node
{
int value;
node *next;
};
node *head;
void addnode(int);
void destroytree();
int main()
{
head=new node;
head=NULL;
int no,ch=1;
while(ch!=0)
{
cout<<"Enter Choice (0 exit, 1 enter): ";
cin>>ch;
if(ch==0) break;
cout<<"Enter no: ";
cin>>no;
addnode(no);
}
cout<<"\nTime to print.\n\n";
destroytree();
cout<<endl;
return 0;
}
void addnode(int no)
{
node *n=new node;
node *trav;
trav=head;
while(trav!=NULL && trav->next!=NULL)
{
trav=trav->next;
}
if(trav==NULL)
{
trav->value=no;
trav->next=NULL;
return;
}
n->value=no;
n->next=NULL;
trav->next=n;
}
void destroytree()
{
node *n;
while(head!=NULL)
{
n=head;
cout<<head->value<<"->NEXT ** ";
head=head->next;
delete n;
}
}
Classes are not allowed. I want 'head' to point to start of the list in all cases except destroytree(). To add a node to the end of the list, start from the 'head' and move on till next is NULL. To destroy the tree, print the first element then delete it. Print the next element and delete it till node->next is NULL
You are dereferencing a null pointer which doesn't make sense.
You are also repeating yourself in the code below so maybe you're not thinking through what you're doing.
if(trav==NULL)
{
trav->value=no;
trav->next=NULL;
return;
}
n->value=no;
n->next=NULL;
trav->next=n;
Apart from assigning the values to the node, all you're looking to do is drop the new node into the end of the list. If you didn't find that by traversing the list it's because the list is empty so the end of the list is the head.
n->value=no;
n->next=NULL;
(trav != NULL ? trav->next : head) = n;
Problem is here
head=new node;
head=NULL; // Remove this line
After you assign new allocated memory to head, you overwrite it with null and trying to dereference it.
Also here, you would dereference NULL pointer as well
if(trav==NULL)
{
trav->value=no;
trav->next=NULL;
return;
}
Since it is redundant you should remove it and use following
n->value=no;
n->next=NULL;
n = (trav != NULL ? trav->next : head);
nullptr is of pointer type , while NULL has the tendency to be integer, so please, in C++11 and higher use nullptr.
if(trav==NULL)
{
trav->value=no;
trav->next=NULL;
return;
}
You are trying to dereference a null pointer.
Remove that piece of code, and add the following to the beginning of addnode:
if(head == NULL)
{
head = new node;
head->value = no;
head->next = NULL;
return;
}
This also allows you to remove the trav == NULL from the while loop condition.
Also note that in main you have
head=new node;
head=NULL;
So you are allocating memory for a node, then you are dropping the only reference you have to that memory address.
You should remove the first of those, and you can replace the assignment of head to NULL to the definition of head (the line that reads node *head;, replace it with node *head = NULL;)
Lastly, if you have a c++11 compliant compiler, use nullptr instead of NULL.
Related
i am trying to write a simple program for deletion and insertion at the end of a linked list. I have managed to insert values at the end perfectly but I cannot understand what to do in deletion.
The delete function is deleteend(), display function is display() and insert function is insertend(int x) but I have problem only with delteend().
#include<iostream>
using namespace std;
struct node
{
int info;
node *next;
};
node *head = NULL;
void insertend(int x)
{
node *last = new node;
last->info = x;
last->next = NULL;
if (head == NULL)
head=last;
else
{
node *temp=head;
while(temp->next!=NULL)
temp=temp->next;
temp->next=last;
}
}
void display()
{
node *np=head;
while(np!=NULL)
{
cout<<np->info<<endl;
np=np->next;
}
}
void deleteend()
{
node *temp=head;
while(temp->next!=NULL)
temp=temp->next;
delete temp;
}
int main()
{
int data;
char ch;
do
{
cout<<"Enter value:";cin>>data;
cout<<endl;
insertend(data);
cout<<"Enter more values?(y/n):";cin>>ch;
cout<<endl;
} while(ch=='y');
cout<<"Your list is"<<endl;
display();
do
{
cout<<"Delete value from end?(y/n):";cin>>ch;
cout<<endl;
if(ch=='y')
deleteend();
} while(ch=='y');
cout<<"Your list is"<<endl;
display();
return 0;
}
You need to maintain a reference to the node before the node you want to delete, so that you can set the pointers correctly.
Since you are only supporting delete from end, your function should look more like this:
void deleteend()
{
// in case we have an empty list to begin with
if (!head) {
return;
}
if (head->next == NULL) {
// our list was one element, so delete head and set our list to null
delete head;
head = NULL;
return;
}
// here, have a node that points to the head
// and then have a node pointer to the next element
// Traverse the list until you hit the end
node *prev = head;
node *end = head->next;
while (end->next != NULL) {
prev = end;
end = end->next;
}
// once we're here, prev should be the second to last element
// and end is the last element
// so delete end and set prev->next to NULL
delete end;
prev->next = NULL;
}
This code can be adapted to delete any arbitrary node from the middle of the list.
For deleteend(), you need to set what is the next to last nodes next pointer to null. This can be done using two pointers, one for the current node and one for the previous node, or by using a pointer to pointer. If using two pointers, in the case of a list with a single node, then there is no previous node, only the head pointer. biryee's answer shows the two pointer method.
Example code for pointer to pointer:
void deleteend()
{
node **ppnode = &head; // ptr to head or a node's next pointer
if(head == NULL)
return;
// advance ppnode so *ppnode points to last node in list
while((*ppnode)->next != NULL)
ppnode = &(*ppnode)->next;
delete(*ppnode); // delete last node
*ppnode = NULL; // set what was pointer to last node to NULL
}
I have managed to create a simple insertion at beginnning of linked list program but now i am struggling with insertion at end of linked list.
The program seems to be able to take values from user but the output list is not coming correct.Could you help me out?
If possible keep along the lines of my program as i am beginner and won't be able to understand a completely different method.
Logic i used-
If list is empty then insert value at beginning else if list is not empty then travel along the list till the next value being pointed at is NULL and then enter the new value in place of NULL.
#include<iostream>
using namespace std;
struct node
{
int data;
node *next;
};
node *start=NULL;
void insertend(int x)
{
node* temp=new node;
if(start==NULL)
temp->data=x;
else
{
while(temp!=NULL)
{
temp=temp->next;
}
temp->next=x;
}
}
void display()
{
node* disp=new node;
while(disp!=NULL)
{
cout<<disp->data<<endl;
disp=disp->next;
}
}
int main()
{
int x;
char ch;
do
{
cout<<"Enter data";cin>>x;
cout<<endl;
insertend(x);
cout<<"Do you want to continue?(y/n)";cin>>ch;
cout<<endl;
}while(ch=='y');
cout<<"Your list:"<<endl;
display();
}
The entry point to your list is the variable start. But you never set it. Take for example the first item a user inputs. You will call insertend(), it will check that start == NULL, but then it never sets start. You must set start = temp or something similar. You have the same problem in the else section -- you loop through the nodes starting with temp, but you should be starting with start. And again in the function display(), you create a pointer to a node and start looping from it, but it will have no data -- you should use start as the starting point of your loop.
struct node{
int data;
node* next;
};
node *first = NULL, *last = NULL;
void insert(int x){
if(first == NULL){
first = new node;
first->data = x;
first->next = NULL;
}else if(last == NULL){
last = new node;
last->data = x;
first->next = last;
last->next = NULL;
}else{
node *n = new node;
n->data = x;
n->next = NULL;
last->next = n;
last = n;
}
}
As you can see I am keeping track of first and last node in the list. Insert function checks if there is anything in the list with if(first == NULL)part. If there isn't it creates the first node. Similar thing happens with the else if. Finally in the else block we create a new node with data x. Then point the node stored in variable last to our new node and set last to be that node.
Here is the display function:
void display()
{
node *disp =first;
while(disp->next != NULL){
cout << disp->data << " ";
disp = disp->next;
}
cout << disp->data;
}
I also recommend that you do a cleanup after your program is finished running since you are creating new nodes.
void cleanup(node* n)
{
if(n->next == NULL)return delete n;
cleanup(n->next);
delete n;
}
and then at the end of main call cleanup(first)
Hope this makes sense :) Have a nice day!
Why does the following code doesn't work? According to my knowledge, when the temp reaches NULL, (new)ing it should create a new node with temp pointing towards it. Oddly, changing the while condition to temp->next!=NULL works perfectly. Any explanation to this?
#include<iostream>
using namespace std;
class node{
int data;
node *next;
public:
node(){}
node(int value):data(value),next(NULL){}
void addNode(node *head,int value){
node *temp=head;
while(temp!=NULL){
temp=temp->next;
}
temp=new node(value);
temp->next=NULL;
}
void display(node *head){
node *temp=head;
while(temp!=NULL){
cout << temp->data << endl;
temp=temp->next;
}
}
};
int main(int argc,char** argv){
node *head=new node(15);
head->addNode(head,50);
head->addNode(head,22);
head->display(head);
cin.ignore();
return 0;
}
you have many mistakes in the pasted code.
if you want to add something to a linked list end like you want here, you first need to find the list end (like you try to do at your code), but you have corner case at start where head is NULL. lets say head is not NULL.
first we find the last node in the list
node * tmp = head;
while(tmp->next != NULL){
tmp = tmp->next
}
now we have the last node in the list. we allocate new one and fill it
tmp->next = new node;
tmp = tmp->next;
tmp->x = data;
tmp->next = NULL;
why your loop doesn't stop. might be that head is not intialized and you have a loop in the list (just a place in memory you travel)
adding with head can be null.
if(tmp != null){
while(tmp->next != NULL){
tmp = tmp->next
}
tmp->next = new node;
tmp = tmp->next;
} else {
head = tmp = new node;
}
Stackoverflow is not allowing me to post images..as I'm a new user.XD
First See this Image
So, when you completed your loop with:
while(temp!=NULL) you end up as shown in diagram.
Now when you enter the code:
temp=new node(value);
temp->next=NULL;
It allocates some memory to temp on heap and is in any way not related to your linked list. So, whenever you use linked list it is advised to allocate to only pointers that consist of your class variables(In this case it is next).
After all temp is just an temporary variable just pointing to nodes of a linked list and allocating memory to it will not change linked list in anyway.
So, always allocate like using temp->next. Not only for allocating but also shifting connections.
This is the reason your code doesn't work in expected way.
You're implementing a Queue as a linked list using pointers. When you're inserting a new node at the end of your Queue/linked list you need to locate the last node of the list so that your temp pointer (which you're using to traverse the list) points to the last node of the list and temp->next points to NULL. Then you can insert the new node by using temp->next = new node(value);You don't need the line temp->next = NULL; after that because that's already done in the constructor when the new node is created.
If you use the condition temp!=NULL then temp will traverse the entire list and end up pointing to the next of the last node instead of pointing to the last node/element of the list (which is what you need). temp won't have any connection with your Queue/linked list. That's why you need the condition
while(temp->next!=NULL){
temp = temp->next;
}
in your addNode function. I've modified your function below:
void addNode(node *head,int value){
node *temp=head;
while(temp->next!=NULL){
temp=temp->next;
}
temp->next=new node(value);
}
My following code print just only first element. In print_list() function, it stops after printing first element. It says after first element, head->next is 0. Shouldn't point towards second element?
I want to simply print whole list.
#include<iostream>
#include<cstdlib>
using namespace std;
struct node {
int x;
node *next;
};
node* add_element(node*);
bool is_empty(node*);
void print_list(node*);
node* search(node*);
int main()
{
node *head;
head=NULL;
node* current=head;
for(int i=0;i<5;i=i+1)
{
if (current==NULL)
{
current=add_element(current);
head=current;
}
else{
current=add_element(current);
}
}
cout<<head->next<<endl;
// DOUBT: head->next gives NULL value. It should give me pointer to 2nd node
print_list(head);
}
node* add_element(node* current)
{
node* temp;
temp=new node;
temp->next=NULL;
cout<<"enter element"<<endl;
cin>>temp->x;
current=temp;
return current;
}
bool is_empty(node* temp)
{
return temp==NULL;
}
void print_list(node* temp)
{
if (is_empty(temp)==false)
{
cout<<"here temp(head)"<<temp->next<<endl;
while(temp!=NULL)
{
cout<<temp->x<<endl;
temp = temp->next;
}
}
}
Print function print first element because you have just one node in the Linked List! Actually the mistake is present in add_element(node*) function, you overwrite address of head node with new node (so having memory leak) as I marked below:
node* add_element(node* current)
{
node* temp;
temp = new node; <---" You allocated memory"
temp->next = NULL; <---" Set next NULL"
cout<< "enter element" << endl;
cin>> temp->x; <---" Assign a value in new node"
// Replace below two line with suggested
current = temp; <---"MISTAKE: Overwrite first node"
"temp next is NULL so losing address of other nodes"
return current; <--- "return first node"
}
Next of new node (so first node) is NULL hence the print function prints only first node's value.
Suggestion:
You should Correct as follows to add new node as a first node in linked list:
temp -> next = current; // new nodes next if present first node
return temp; // new code becomes first node
Be careful current should be NULL initially.
With my suggestion in add_element() function also change the for loop code in main() as follows:
for(int i=0; i < 5; i = i + 1){
current = add_element(current);
}
head = current;
And check the working code at Codepade (instead of user input I added value using y = 100 variable).
Edit To append new node:
You need to check whether new node is first node of not (read comments).
// returns first node address in linked list = head
node* add_element(node* head){
node *temp, *new_nd;
// Create new node
new_nd = new node;
new_nd->next = NULL;
cout<<"enter element"<<endl;
cin>>new_nd->x;
// Is new node is the first node?
if(!head)
return new_nd;
// move to last
temp = head;
while(temp->next) temp = temp->next;
// add new node at last
temp->next = new_nd;
// return old head
return head;
}
Also simply main() as below:
int main(){
node *head = NULL;
for(int i = 0; i < 5; i = i + 1){
head = add_element(head);
}
print_list(head);
}
check this working code.
Your problem is here:
node* add_element(node* current)
{
node* temp; //You created a new node
temp=new node; //You allocated it here
temp->next=NULL; //You set its next property to null
cout<<"enter element"<<endl; //
cin>>temp->x;
current=temp; //This should be current->next = temp. You are overwriting it!
return current; //And now you are returning essentially the temp object that
//You created and you set its next property to NULL
}
You are assigning the node you created in temp = new node to the current node that was passed in. What you want to do is assign the node you just created to the current node's next property. It should be current->next = temp
head->next is NULL because you set it so in add_element(). To have a linked list, you should set current->next = temp.
As you're using C++, you might consider using std::list instead of implementing your own linked list.
if (current==NULL)
{ current=add_element(current);
head=current;
}
else
{ current->next=add_element(current);
current=current->next;
}
The correct code.
You have to make a small correction in the loop.
You have to add a new node and then make it point to the next of the current node.
so the simplified code is current->next=add_element(current)
and then make current point to the new current.
I've checked the boards and could not find any help with this. I find it easy to implement recursive functions given base and general cases, but this doesn't work the way I do it. I'm supposed to iterate down a list until I reach the tail of a linked list. If the next node is NULL, then I have to store the value at the last node, remove that node, and return the value. So it's similar to a dequeue method, except it's performed recursively. What am I doing wrong?
int LinkedList::removeTailRec(Node *n)
{
// check for the base case(s)
if(n->next == NULL)
{
Node *tmp = new Node();
tmp = n;
int val = n->value;
tmp = NULL;
return val;
}
else
return removeTailRec(n->next);
// else call the recursive method
}
First, I recommend you use nullptr instead of NULL.
Then, onto your code. You're actually not removing anything from your list.
if(n->next == NULL)
{
Node *tmp = new Node();
^^^^^^^^^^
//Useless, and dangerous. This memory is never free'd
tmp = n;
int val = n->value;
tmp = NULL;
^^^^^^^^^^
//You just set a local variable to NULL, you're not deleting anything
return val;
}
If you want to remove the node, you'll have to keep a reference to the previous node (e.g. having a doubly linked list, that is, having a pointer to the next element and a pointer to the previous element in each node, or working on the previous node directly).
Set this previous node's next to nullptr, store the node's value and then delete the Node pointer.
One way to do this is to work with the pointer to the next node :
int LinkedList::removeTailRec(Node *n)
{
//EDIT: Adding a check for n validity
if(!n){
//Here, you should have a way of detecting
//a call to your method with a null pointer
return 0;
}
Node* nextNode = n->next;
// check for the base case(s)
if(nextNode->next == nullptr)
{
//Get the next node value
int val = nextNode->value;
//Set the current node next member to nullptr
n->next = nullptr;
//Free the last node
delete nextNode;
return val;
}
else{
return removeTailRec(n->next);
}
// else call the recursive method
}
You are storing the result but not deleting it from linked list. You can return result in another variable (pointer : result).
Node* getTail(Node *n,int *result){
//u can even free the memory
if(!n->next)
{
result=n->value;
return NULL;
}
n->next=getTail(n->next,result);
}
or you can do it other way
int getTail(Node *n)
{
if(!n) return 0;
if(n->next)
{
if(!n->next->next)
{
Node *frnode=n->next;
int result=n->next->value;
n->next=NULL;
delete frnode;
return result;
}
getTail(n->next);
}
You are not removing last node in your code, and you leak another (temporary) node here.
To remove last node you have to zero the link in the previous node.
Your code should look like
...
if (n == NULL || n->next == NULL)
throw std::out_of_range("node");
if(n->next->next == NULL)
{
int val = n->next->value;
delete n->next;
n->next = NULL;
return val;
}
else ...
Be aware of the fact that c++ is not a functional language and has no optimizations for tail recursion, so in real application as your lists grow big enough you'll eventually have failure with stack overflow =) use Haskell or Erlang for this style of programming, in c++ use for or while.
You should set the Node n's previous Node's next field to NULL when n is the tail Node.