Inserting a node at the end of a linked list - c

#include <stdio.h>
#include <conio.h>
struct node
{
int data;
struct node* next;
};
int main()
{
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = (struct node*)malloc(sizeof(struct node));
second = (struct node*)malloc(sizeof(struct node));
third = (struct node*)malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
struct node* new1;
struct node* temp1;
temp1 = head;
while(temp1->next != NULL)
{
temp1 = temp1->next;
}
new1 = (struct node*)malloc(sizeof(struct node));
temp1->next = new1;
new1->data = 5;
new1->next = NULL;
while(temp1 != NULL)
{
printf("%d ",temp1->data);
temp1 = temp1->next;
}
return 0;
}
This is the program for inserting a node at the end of linked list. The expected output is = 1 2 3 5, 5 is the new node's value here. But the current output is = 3 5. I don't know where am I wrong. Any answer will be appreciated.

while(temp1->next != NULL)
{
temp1 = temp1->next;
}
After this loop your temp1 is at the end of the list and you are adding a node at the end of the list.
Now you are trying to print from temp1 obviously you will get only 2 nodes new one and the one before it.
If you want the whole list print from head.
Just before printing after adding your new node. Point temp1 to head.
temp1 = head;
while(temp1 != NULL)
{
printf("%d ",temp1->data);
temp1 = temp1->next;
}

One thing to remember when using something like you did to get to the end of the list: If you just say third->next = first, then it will go on forever. This is something to watch out for, and also something you may want to play with. Maybe consider adding a list_size integer somewhere so that infinite looping does not happen.

Related

Unexpected output while printing a linked list

I got this code on codeblocks 13.12 in lubuntu 16.04
The program is running but the problem is that the first insertion is duplicated that is,
lets say i first insert integer "4" to the linked list. But i get the output as:
4 ,4 ,
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* head = NULL;
void Insert(int c)
{
if(head == NULL) {
struct node* temp = malloc(sizeof(struct node));
temp -> data = c;
temp -> next = NULL;
head = temp;
}
struct node* temp = malloc(sizeof(struct node));
temp -> data = c;
temp -> next = NULL;
struct node* temp1 = head;
while (temp1->next != NULL) {
temp1 = temp1->next;
}
temp1 -> next = temp;
}
void print() {
struct node* temp = head;
printf("list is: \n");
while (temp != NULL) {
printf( "%d ,",temp->data);
temp = temp->next;
}
}
int main () {
printf("How Many Numbers?\n");
int a ,b ,c;
scanf("%d" , &b);
for(a = 0;a<b;a++) {
printf("Enter the numbers \n");
scanf("%d",&c);
Insert(c);
print();
}
return 0;
}
the problem is that the first insertion is duplicated
Reason:
You've mentioned if(head==NULL) correctly to check whether inserted node is first node or not but after this you did not mention else to restrict compiler.
So the compiler compiles both the if block and the code following it
So another node gets created after head with the same value c
that's the reason when you insert c=4, you get 4,4, as output
Solution
Try using your insert() with an else condition as
void Insert(int c)
{
if(head == NULL)
{
struct node* temp = malloc(sizeof(struct node));
temp -> data = c;
temp -> next = NULL;
head = temp;
}
else
{
struct node* temp = malloc(sizeof(struct node));
temp -> data = c;
temp -> next = NULL;
struct node* temp1 = head;
while (temp1->next!= NULL)
temp1 = temp1->next;
temp1 -> next = temp;
}
}
suggestion : you've mentioned this twice in you insert() function
struct node* temp = malloc(sizeof(struct node));
temp -> data = c;
temp -> next = NULL;
just allocate temp once and then insert it at approprite position using if-else conditions. This reduces the number of lines of code too. do it this way:
void Insert(int c)
{
struct node* temp = malloc(sizeof(struct node));
temp -> data = c;
temp -> next = NULL;
if(head == NULL)
{
head = temp;
}
else
{
struct node* temp1 = head;
while (temp1->next!= NULL)
temp1 = temp1->next;
temp1 -> next = temp;
}
}
That is because the Insert function "falls through" after initialising the first item, and inserts it again. Add return at the end of the code block.
void Insert(int c)
{
if(head == NULL) {
struct node* temp = malloc(sizeof(struct node));
temp -> data = c;
temp -> next = NULL;
head = temp;
return; //<-- add this line
}
...

Segmentation fault while implementing linked list in C

I'm trying to create a simple linked list and insert a node at the end of the list. I'm getting a segmentation fault.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *link;
};
void create(struct node *head){
struct node* second = NULL;
struct node* last = NULL;
second = (struct node*)malloc(sizeof(struct node));
last = (struct node*)malloc(sizeof(struct node));
second -> data = 2;
last -> data = 3;
head -> link = second;
second -> link = last;
last -> link = NULL;
}
void insert_ending(struct node *head){
struct node* temp = NULL;
struct node* temp1 = NULL;
temp1 = (struct node*)malloc(sizeof(struct node));
temp1 -> data = 5;
temp1 -> link = NULL;
temp = head;
while(temp != NULL){
temp = temp -> link;
}temp -> link = temp1;
}
void PrintList(struct node *head){
while( head != NULL ){
printf(" %d -->", head -> data);
head = head -> link;
}
printf("\n");
}
int main(){
struct node* head = NULL;
head = (struct node*)malloc(sizeof(struct node));
head -> data = 1;
head -> link = NULL;
create(head);
PrintList(head);
insert_ending(head);
PrintList(head);
return 0;
}
I'm getting a segmentation fault. The output is as follows.
1 --> 2 --> 3 -->
Segmentation fault (core dumped)
in your insert function you need to change to :
temp = head;
while(temp -> link != NULL){
temp = temp -> link;
}
temp -> link = temp1;
the reason is that when you loop with while until temp == null, you can't afterward do: temp -> link because temp is allready null.
In the function 'insert_ending' in the while loop you want to change the
condition from:
while ( temp != NULL )
to:
while ( temp->link != NULL )
because now once the loop is finished, temp is NULL and then you try to dereference it (a NULL pointer) and get an error.

Insertion in a doubly linked list in C

My program keeps on crashing. I think there's a problem in my logic. Please help! Thanks!
struct node{
int data;
struct node *prev,*next;
} *head = NULL;
void insert(){
struct node* temp = (struct node*) malloc (sizeof (struct node*));
int value;
printf("Enter an element");
scanf("%d",&value);
temp -> data = value;
temp -> next = NULL;
temp -> prev = NULL;
if(value < head -> data || head == NULL){
temp -> next = head -> next;
head = temp;
return;
}
while(head->next != NULL && value > head -> next -> data)
head = head -> next;
temp -> next = head ->next->prev;
head -> next = temp -> prev;
while (head -> prev != NULL)
head = head -> prev;
}
Try this:
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *prev,*next;
} *head = 0;
void insert(int value){
struct node* temp = (struct node*) malloc (sizeof (struct node));
//int value;
//printf("Enter an element");
//scanf("%d",&value);
temp -> data = value;
temp -> next = 0;
temp -> prev = 0;
if(head == 0) {
// no head, make temp the head
head = temp;
} else if(value > head->data) {
// put temp in front of the head
temp->next = head;
head->prev = temp;
head = temp;
} else {
// put temp after the head
struct node *this = head;
struct node *prev = 0;
while(this && this->data > value) {
prev = this;
this = this->next;
}
temp->next = this;
temp->prev = prev;
prev->next = temp;
if(this) {
this->prev = temp;
}
}
}
int main() {
insert(1);
insert(3);
insert(4);
struct node *t = 0;
for(t = head; t; t = t->next) {
printf("%d\n", t->data);
}
}
This one compiles and sorts in descending value. Note I commented out your scanf
and made insert take a parameter.
the space you malloc is not enough.
change
struct node* temp = (struct node*) malloc (sizeof (struct node*));
to
struct node* temp = (struct node*) malloc (sizeof (struct node));
As a start, think about these two lines and what happens if head == NULL:
if(value < head->data || head == NULL){
temp->next = head->next;
Specifically what is head->next?
There are two core problems I see.
You are not allocating sufficient space for a node struct. sizeof(struct node *) returns the size of a node pointer, not a node. This:
struct node* temp = (struct node*) malloc (sizeof (struct node*));`
... should be this:
struct node* temp = (struct node*) malloc (sizeof (struct node));
Be careful with pointers:
if (value < head -> data || head == NULL)
... what is the value of head->data if you haven't initialized head? (e.g. it is still NULL). Your program will fetch data from address NULL with an offset for field data. Address NULL is not valid / is part of protected memory space, your OS won't like this :).
You should first check if head is NULL. If it is, then you can't reference fields of head as they are invalid (in any situation). Be careful with multi-part conditional expressions to check for struct pointer NULL presence prior to subsequent parts that reference struct fields, also.

Debugging C Linked List Program caught in infinite loop

So this is a very simple program to create and display a linked list. Here I'm getting caught in the display loop, and I'm seeing infinite '2->2->2->...' on screen.
After debugging, I can see that my program ALWAYS goes into the if statement of insertNode() whereas it should only go there ONCE i.e. when the linked list is initialized.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node * next;
};
struct node * head = NULL;
struct node * curr = NULL;
void insertNode(struct node * temp2) {
if (head == NULL) {
head = temp2;
head->next = NULL;
}
else {
temp2->next = head;
head = temp2;
}
}
void display() {
curr = head;
while (curr->next != NULL)
{
printf("%d->",curr->data);
curr = curr->next;
}
}
void main() {
struct node * temp = (struct node *) malloc (sizeof(struct node));
temp->data = 5;
insertNode(temp);
temp->data = 6;
insertNode(temp);
temp->data = 1;
insertNode(temp);
temp->data = 2;
insertNode(temp);
display();
}
You should allocate and create new node for each data when inserting it in the linked list.
void main() {
struct node * temp = (struct node *) malloc (sizeof(struct node));
temp->data = 5;
insertNode(temp);
temp = malloc (sizeof(struct node));
temp->data = 6;
insertNode(temp);
temp = malloc (sizeof(struct node));
temp->data = 1;
insertNode(temp);
temp = malloc (sizeof(struct node));
temp->data = 2;
insertNode(temp);
display();
}
As you are using same node to add as multiple nodes, its making the circular list.
Your insertNode() looks ok.
You are setting next of temp2 to head, and then head to temp2. So in fact next node of temp2 is temp2, that's why you have infinite loop.
In you main you have one pointer to the temp and you continue inserting the same node and it ends up pointing to itself. You now have a circular list that's why you have an infinite loop.
You are getting an infinite loop because you only have one node. Doing temp->data = 5; and then temp->data = 6; does not create a new node. So when you add the same node into the list again, the next pointer in the node points to itself. So your while loop in display never terminates, because the next node is always the current node.

Seg fault linked list recursion in C

I can't figure out why I'm seg faulting. The basic idea is to insert integers in order recursively using a linked list.
node* insert(node** head, int integer)
{
node* temp = malloc(sizeof(node));
node* temp1;
node* newNode;
if(*head == NULL)
{
temp->num = integer;
temp->next = *head;
*head = temp;
}
else if((*head)->num > integer)
{
temp = *head;
temp1 = temp->next; //breaks the link
temp->next = newNode; //creates a new node
newNode->num = integer; //adds int
newNode->next = temp1; //links new node to previously broken node
temp1->next = *head; //next node is NULL
*head = temp1; //Makes next node head again
}
else
insert(&((*head)->next), integer);
return(temp);
}
I ran this code in GDB and it seg faults at temp1->next = *head but I don't understand why. I even put notes to help myself but I guess it isn't working. Can someone please tell me why I'm seg faulting? Thanks.
temp1 = temp->next;
should be before
temp = *head;
In case that the (*head)->num > integer and If you want to insert the integer in the header than your code is complicated and wrong. you can do it in this way:
else if((*head)->num > integer)
{
temp->next = *head;
temp->num = integer;
*head = temp;
}
and the
temp = malloc(sizeof(node));
should be called only into the
if(*head == NULL)
and into
else if((*head)->num > integer)
So your final function could be like this
node* insert(node** head, int integer)
{
node* temp;
if(*head == NULL)
{
temp = malloc(sizeof(node));
temp->num = integer;
temp->next = *head;
*head = temp;
}
else if((*head)->num > integer)
{
temp = malloc(sizeof(node));
temp->next = *head;
temp->num = integer;
*head = temp;
}
else
temp = insert(&((*head)->next), integer);
return(temp);
}
I test the insert function with:
int main (void) {
node *tmp, *head = NULL;
insert(&head, 5);
insert(&head, 7);
insert(&head, 3);
insert(&head, 6);
insert(&head, 4);
insert(&head, 2);
for (tmp = head; tmp!=NULL; tmp = tmp->next) {
printf("tmp->num %d\n",tmp->num);
}
}
and it works succefully!
$ ./test
tmp->num 2
tmp->num 3
tmp->num 4
tmp->num 5
tmp->num 6
tmp->num 7
So the first time you go through this, head is null and you've got a case for that.
The next time through, head has a pointer, and there is no next node. The head->next is NULL.
So when you get to:
temp1 = temp->next;
That's setting it equal to NULL. And when you get to
temp1->next = *head; //next node is NULL
Whoa there, temp1 is null. There is no such thing as temp1->next, that's looking for a structure where there is none.
Edit:
And you're throwing away the memory you just allocated when you set temp = *head. You probably shouldn't be allocating memory until you're sure you need it. I mean, you call a new instance of insert() every time the number is less than the target. Each pass you allocate some memory that you don't actually use. And you probably wanted to allocate memory for newnode, not temp.
And you should probably use a better naming scheme. I mean, the second time you call insert, it's no longer the head. integer could be something more like intToInsert or newValue. temp1 is more like savedTail. Minor issue, but it helps keep things straight, and it's a good habit to get into.
Finally, think about what happens when you've gone through the list, found where the new item belongs, made a new node, set it's ->next field to the rest of the tail, and returned. ... now what? the previous node has a next value that's still pointing to what it was before. You need to update that link as well.
Lets assume that the linked list currently has only one node.
So *head = some node.
*head->next = NULL.
Now lets look into the code:
node* insert(node** head, int integer)
{
node* temp = malloc(sizeof(node));
node* temp1;
node* newNode;
if(*head == NULL) // condition = false
{
temp->num = integer;
temp->next = *head;
*head = temp;
}
else if((*head)->num > integer) // let's assume condition = true
{
temp = *head;
temp1 = temp->next; //breaks the link // temp1 = NULL
temp->next = newNode; //creates a new node // temp1 is not changed
newNode->num = integer; //adds int
newNode->next = temp1; //links new node to previously broken node
temp1->next = *head; //next node is NULL // NULL->next !!!
*head = temp1; //Makes next node head again
}
else
insert(&((*head)->next), integer);
return(temp);
}
*head = temp1;
should be before
temp1->next = *head;

Resources