I have the following C code to copy a linked list(taken from Stanford CS Library files):
struct Node* CopyList(struct Node* head)
{
struct Node* current = head;
struct Node* newList= NULL;
struct Node* tail= NULL;
while (current !=NULL)
{
if(newList==NULL)
{
newList=malloc(sizeof(struct Node));
newList->data=current->data;
newList->next=NULL;
tail= newList;
}
else
{
tail= malloc(sizeof(struct Node));
tail= tail->next;
tail->data=current->data;
tail->next = NULL;
}
current= current->next;
}
return(newList);
}
I have the following as a part of my main function:
struct Node* head = NULL;
for (i=3; i >=1;i--) //insert 3 elements into the linked list
{ //push inserts elements in the front
Push(&head,i);
} //now a linked list 1->2->3->NULL is formed
struct Node* newlst= CopyList(head); // copies contents into a new linked list
I am compiling the code using Bloodshed Dev C++. I don't get any compilation errors but when I run it, it just crashes. What could be the issue with this? Am I passing the right parameter to the CopyList function?
Your problem lies here, in the else bit:
tail = malloc (sizeof (struct Node));
tail = tail->next;
tail->data = current->data;
tail->next = NULL;
You are allocating a new node and setting tail to point to it (in that first line). Then you are using tail as if it's the old tail. Specifically, that second line will give you a rogue pointer (as you haven't initialised the new node with valid pointers), which will probably crash in the third line when you try to dereference it.
You need something like:
// First, set up the new node.
newList = malloc (sizeof (struct Node));
newList->data = current->data;
newList->next = NULL;
// Then, adjust the tail pointers.
tail->next = newList;
tail = newList;
Actually, looking back at your code, what you probably intended was:
tail->next = malloc (sizeof (struct Node)); // use tail->next, not tail.
tail = tail->next;
tail->data = current->data;
tail->next = NULL;
which achieves the same result.
I suppose I should mention that you really ought to check the return values from malloc in case you run out of memory. You can do this with something like:
tail->next = malloc (sizeof (struct Node)); // use tail->next, not tail.
if (tail->next == NULL) {
// do something here for recovery.
return;
}
// Only continue here if the allocation worked.
tail = tail->next;
tail->data = current->data;
tail->next = NULL;
Without checks like that, you will get crashes when you run out of memory.
You are allocating memory for tail, it should be tail->next. Without this you would lose previous pointers.
Modified code
struct Node* CopyList(struct Node* head)
{
//.... same as before
while (current !=NULL)
{
if(newList==NULL)
{
//.... same as before
}
else
{
tail->next = malloc(sizeof(struct Node));
tail= tail->next;
tail->data=current->data;
tail->next = NULL;
}
current= current->next;
}
return(newList);
}
Shash
If it just dies, that is usually a sing of accessing an invalid pointer. Most likely a null pointer.
Here is your problem:
tail= malloc(sizeof(struct Node));
tail= tail->next;
tail points to an unitialised area of memory. So tail->next may be anything.
Try
tail->next= malloc(sizeof(struct Node));
tail= tail->next;
Consider this line -
tail = tail->next;
When you are creating the first node in the new list, it's OK, both the newList and tail points to that node.Now think what will happen when a second node will be created in the new list -
tail = malloc(sizeof(struct Node)); // tail points to the new node
tail = tail->next; // You are assigning new node's next to tail, but
// did you initialize next to anything?
So next isn't initialized to anything, and you are assigning it to tail, so tail now contains garbage. When you are assigning it some value in the next two lines, your program will certainly crush.
Instead of assigning new node to tail, you need to assign it to tail's next -
tail->next = (struct Node *) malloc(sizeof(struct Node) * 1);
in else block you have written this code
tail= malloc(sizeof(struct Node));
tail= tail->next;
tail->data=current->data;
tail->next = NULL;
Line 1: tail is pointing a node and all the member of this node is having value as tail has not been initialised.
Line2: tail->next which has garbage value is being assigned to tail. Now tail is not pointing any mallocked memeory. And you lost the pointer of the already mallocked memory
So actually linklist is not being made here
Related
I have been using linked list and I have used the following code for append function which i wrote in a new file and it works perfectly but when I copy it my main code it gives segmentation fault at while(current->next != null) . It does not give any warning while compiling so I don't know whats the issue here.
// Linked List Node for Reading Comments
struct Node{
char value;
struct Node *next;
};
void append(struct Node * headNode, char newElement){
struct Node *newNode = malloc(sizeof(struct Node)); //Dynamically Allocating Memory for New Node
struct Node *current = headNode; //Creating A Node to traverse the linked list
newNode->value = newElement; //Assigning the values of newNode to the given value
newNode->next = NULL; //Setting next value to be null since its the last node
if (headNode == NULL){ //Checking if headnode is empty
headNode = newNode; //Assigning headnode and tailnode to be newnode
}
else {
while(current->next != NULL){ //Traversing through the linked list
current = current->next;
}
current->next = newNode; //Setting tailnode's next to be newnode
}
}
void printLinkedList(struct Node* headNode){
while(headNode != NULL){
fprintf(stderr,"%c",headNode->value);
headNode = headNode->next;
}
}
If anyone can comment on this please do.
Your code does not allow to add a node to an empty list. If you try and did not initialise your head pointer on the calling side, you may get such behavior.
For instance, in main you could have:
struct Node* head; // not initialised
append(head, 'a');
printLinkedList(head);
These are then the issues:
If head happens to be not NULL, then the else block will kick in and the current pointer will reference some unintended memory address.
append will not change the head variable of main. It will only modify a local variable that happens to have a similar name (headNode).
To correct, pass the address of head to the append function, and let append deal with this accordingly:
void append(struct Node ** headNode, char newElement) {
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *current = *headNode;
newNode->value = newElement;
newNode->next = NULL;
if (*headNode == NULL) {
*headNode = newNode;
} else {
while(current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
}
Note the additional * wherever headNode occurs. In main:
struct Node* head;
append(&head, 'a');
printLinkedList(head);
I have been having trouble with this linked list specifically it seems like my head pointer is not linking to the rest of my list and I am confused as to why it is not. Where I insert my head pointer by pointer by reference it is not connected to the linked list referenced in main. unless the list is not linked together in the main function and I am missing something.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node * next;
} Node;
typedef Node * Nodeptr;
void printlist (Node * head){
Node * n = head;
while(n != NULL){
printf("%d\n",n ->number);
n = n ->next;
}
}
void sumlist (Node * head){
Node * n = head;
int sum;
while(n != NULL){
sum = n ->number +sum;
n = n ->next;
}
printf("the total of all numbers in this list is %d",sum);
}
search(head){
}
int main(){
int i =0;
Nodeptr head=NULL;
if((head = malloc(sizeof(Node))) == NULL)
return 0;
head->number =rand()%50+50;
head ->next = malloc(sizeof(Node));
int n;
Nodeptr newnode = NULL;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
}
printlist(head);
sumlist(head);
return 0;
}
The error is that you are linking everything as next of head
head -> next = newnode;
You need to use a pointer that gets updated:
Nodeptr newnode = NULL;
Nodeptr last = head;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
last -> next = newnode;
last = last->next;
}
You should also change this:
head ->next = malloc(sizeof(Node)); // otherwise you will lose this element.
into
head ->next = NULL;
You execute these steps in a loop:
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
You are setting the newnode->next to point to null, and head->next to point to newnode.
This means, each time through the loop your head gets a new next, and that's it.
Effectively, each time you pass through the loop you drop the previous newnode on the floor, and link to a new one. At the end, you'll have head pointing to 1 node, and you'll have 98 nodes dropped on the floor that you can't reach.
You need to either maintain a "tail" pointer, or a copy of "head", and set head or tail or something to the most recent value of newnode. Then, you can set tail->next = newnode; tail = newnode; which will continually extend your list, rather than overwriting the same head->next each time.
In this code:
Node *CopyList(Node **head) {
Node *current = *head;
Node *NewNode = NULL;
Node *tail = NULL;
while (current != NULL ) {
if (NewNode == NULL) {
NewNode = malloc(sizeof(Node));
NewNode->data = current->data;
NewNode->next = NULL; // routine
tail = NewNode;
} else {
tail->next = malloc(sizeof(Node)); // here
tail = tail->next;
tail->data = current->data;
tail->next = NULL;
}
current = current->next;
}
return(NewNode);
}
Why are we assigning tail->next to the result of a malloc() call? Evidently, if we don't do so a segmentation fault occurs.
Why didn't we just allocate tail instead of tail->next? What are some situations in which I should allocate next like this?
It is just a convenience, to avoid an extra variable:
Node* temp = malloc(sizeof(Node)); // here
temp->data = current->data ;
temp->next = NULL ;
tail->next = temp ;
tail = tail->next;
Why we didn't just allocate tail instead tail->next ?
Tail is already allocated, it is acting as the previous node, so we can link it to the next one. We allocate a new node and link tail to that node with tail->next = that_node.
here NewNode represents New Linked list head. So for the first time in while loop it gets allocated so it's not getting changed next time onward. Coming to your question that 'tail->next' instead of 'tail' because for the first time when 'NewNode == NULL' then 'tail = NewNode' gets executed means tail is having NewNode address. So next onward you need to copy next block into 'tail->next' as tail is already having 'NewNode'.
I am trying to insert into a doubly linked list. I am then trying to print the list in both forward and reverse direction. I have created a head node and I am trying to insert another one, but I am unable to do so. The program shows a runtime error.
Please find my code below. Any help would be appreciated.
#include<stddef.h>
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
struct node *prev;
};
void insertAfter(struct node *node, int new_data){
if (node == NULL)
{
printf("the given previous node cannot be NULL");
return;
}
struct node* new_node = (struct node*)malloc(sizeof(struct node));
node->data = new_data;
node->next = new_node;
new_node->prev = node;
new_node->next - node->next;
if(new_node->next!=NULL)
new_node->next->prev = new_node;
}
void printlist(struct node *node){
struct node *last;
printf("Traversal in forward direction\n");
while(node!=NULL){
printf("%d\n",node->data);
last = node;
node=node->next;
}
printf("Traversal in backward direction\n");
while(last!=NULL){
printf("%d\n",last->data);
last=last->prev;
}
}
int main()
{
struct node *head;
struct node *tail;
head->data = 5;
tail->data = 10;
head->next = tail;
head->prev = NULL;
tail->next = NULL;
insertAfter(head, 8);
printf("\n Created DLL is: ");
printlist(head);
return 0;
}
There are several problems here.
First, as pointed out by #Igor, you are not allocating any memory for your head and tail nodes. You should also set tail->prev = head.
Second, the order in which insertAfter sets the link pointers causes node->next to be overwritten before it is used in setting new_node->next. This causes new_node->next to point back to new_node instead of to whatever was following node. You should set new_node->next and new_node->prev before you modify node. It also appears that you have used a minus sign instead of an equals in the "assignment" of new_node->next.
Third, in printlist, you should initialize last to NULL in case the list is empty; otherwise, you will attempt to walk the list backwards from an undefined starting (ending) point.
You want new_node->next to be the same as new_node?
if not, you'd better swap these two lines, in InsertAfter:
node->next = new_node;
new_node->next - node->next;
You need to allocate memory for your pointers head and tail.
int main()
{
struct node *head;
struct node *tail;
head = malloc(sizeof(struct node)); //allocating memory to head
tail = malloc(sizeof(struct node)); //allocating memory to tail
head->data = 5;
tail->data = 10;
head->next = tail;
head->prev = NULL;
tail->next = NULL;
insertAfter(head, 8);
printf("\n Created DLL is: ");
printlist(head);
return 0;
}
Also, never cast the return value of malloc, therefore change:
struct node* new_node = (struct node*)malloc(sizeof(struct node));
to
struct node* new_node = malloc(sizeof(struct node));
I am rather new to C, and am working on copying a Linked List. It seg faults somewhere in the while loop, I think I am having some pointer troubles. Also, I'm not sure if I need to malloc each 'next' node. Do I? It makes sense for me to have to.
struct node* copyList() {
struct node* walker = head; // starting point to "walk" the list
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = walker->data;
while( walker != NULL ){ // done when we reach the node pointing to NULL
walker = walker->next; // advance walker to the next node in the list
temp = temp->next;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = walker->data;
}
return walker;
}
The node strut is as follows
struct node {
int data;
struct node* next;
};
Suppose you reach last node..
Now inside loop , you increment walker..so now walker = NULL..
so this statement gives an error temp->data = walker->data..
Also you are just creating nodes and copying data not connecting your new linked list..
You need to maintain new Head pointer to return at the end
Keep reference to previous node so that you can link it to current node
Update the pointers
Change it along the lines of this..
struct node* copyList() {
struct node* walker = head; // starting point to "walk" the list
struct node* newHead=NULL,temp,prev=NULL;
while( walker != NULL ){ // done when we reach the node pointing to NULL
temp = (struct node*)malloc(sizeof(struct node)); //create new node
temp->data = walker->data; //copy data
if(prev==NULL) //if its first node
newHead = temp; //new head pointer
else
prev->next = temp; //else link to previous node
prev = temp; //update pointers
walker = walker->next;
}
return newHead;
}
Just where do you expect the value of temp->next in your loop to come from?
Also, to get a bit more meta, you might be vastly better off using e.g. std::list in C++ rather than implementing your own data structures like this. Even for experienced engineers, such efforts are notoriously error-prone.