C program to traverse a singly linked lisk - c

I have written a C program to implement the concept of traversing a singly linked list. The program first creats the list by asking for the user input and then displays/ traverses through the created list. When i run this code, it sucessfully creates the linked list, but on displaying the created list, it produces an infinite loop.
`
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
} *head;
int main(){
struct node *newNode, *temp;
int n;
printf("Enter number of Nodes: ");
scanf("%d",&n);
if(n <= 1){
printf("Invalid Input Nodes should Nodes should be greater than 1");
exit(0);
}
else{
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL){
printf("No Memory Allocation");
exit(0);
}
else{
printf("Node Data 1: ");
scanf("%d",&head -> data);
head -> next = NULL;
temp = head;
}
newNode = (struct node *)malloc(sizeof(struct node));
if(newNode == NULL){
printf("No Memory Allocation");
exit(0);
}
else{
for(int i = 2; i <= n; ++i){
printf("Node Data %d: ",i);
scanf("%d",&newNode -> data);
newNode -> next = NULL;
temp -> next = newNode;
temp = temp -> next;
}
}
//Traversal
struct node *ptr;
ptr = head;
if(ptr == NULL)
{
printf("Empty list..");
}
else
{
while (ptr != NULL){
printf("\n%d",ptr->data);
ptr = ptr -> next;
}
}
}
return 0;
}
`

In this for loop
for(int i = 2; i <= n; ++i){
printf("Node Data %d: ",i);
scanf("%d",&newNode -> data);
newNode -> next = NULL;
temp -> next = newNode;
}
the same pointer newNode is assigned to the data member temp->next that is equivalent to the expression head->next because within the loop the pointer temp is not changed.
You need to allocate new nodes in the loop and reassign the pointer temp.
Also you need to check the entered value for the variable n. For example if n is set to 1 then there will be a memory leak.
And there is neither infinite loop provided that the entered value for the variable n is not equal to INT_MAX.
The program can look the following way
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
struct node
{
int data;
struct node *next;
} *head = NULL;
unsigned int n = 0;
printf( "Enter number of Nodes: " );
scanf( "%u", &n );
if (n != 0)
{
head = malloc( sizeof( struct node ) );
if (!head)
{
puts( "No Memory Allocation" );
exit( 0 );
}
else
{
printf( "Node Data 1: " );
scanf( "%d", &head->data );
head->next = NULL;
unsigned int i = 0;
for (struct node *temp = head; ++i < n; temp = temp->next)
{
if (( temp->next = malloc( sizeof( struct node ) ) ) == NULL)
{
puts( "No Memory Allocation" );
break;
}
temp->next->next = NULL;
printf( "Node Data %u: ", i + 1 );
scanf( "%d", &temp->next->data );
}
for (const struct node *current = head; current != NULL; current = current->next)
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
}
}
The program output is
Enter number of Nodes: 5
Node Data 1: 1
Node Data 2: 2
Node Data 3: 3
Node Data 4: 4
Node Data 5: 5
1 -> 2 -> 3 -> 4 -> 5 -> null
Pay attention to that you need to append the program with the code that will free all the allocated memory.

Related

Deleting and inserting nodes in a linked list behave differently (?)

I'm trying to learn linked lists from King (2008) "C Programming: A Modern Approach", 2nd ed and I'm puzzled by the behaviour of the deletion operation as compared to the insertion operation.
The author writes (p. 429):
Note that add_to_list doesn't modify the list pointer. Instead, it
returns a pointer to the newly created node....Getting add_to_list
to update first, turns out to be tricky.
Now while deleting the first node doesn't modify the original list, deleting nodes in the interior or the end does modify the original list. But delete_from_list is also making a copy of the first pointer, so why can it modify first (while add_to_list cannot)?
What am I missing here?
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node *next;
};
struct node *delete_from_list(struct node *, int);
struct node *add_to_list(struct node *, int n);
int main(int argc, char **argv) {
// setup a linked list
// list's head
struct node *first= NULL;
// first node
struct node *new_node= malloc(sizeof(struct node));
new_node->value= 10;
new_node->next= first;
first= new_node;
//second node
new_node = malloc(sizeof(struct node));
new_node->value= 20;
new_node->next= first;
first= new_node;
//third node
new_node= malloc(sizeof(struct node));
new_node->value= 40;
new_node->next= first;
first= new_node;
//fourth node
new_node= malloc(sizeof(struct node));
new_node->value= 30;
new_node->next= first;
first= new_node;
int i;
struct node *head= first;
printf("\n------------------------\n");
printf(" Original nodes: ");
for(i=0; head!= NULL; head= head->next, i++)
printf("\n%d-ith value: %d ", i, head->value);
printf("\n------------------------\n");
struct node *first_no20= delete_from_list(first, 20);
struct node *head_no20= first_no20;
printf("\n------------------------\n");
printf(" Nodes without 20: ");
for(i=0; head_no20!= NULL; head_no20= head_no20->next, i++)
printf("\n%d-ith value: %d ", i,head_no20->value);
printf("\n------------------------\n");
printf("\n------------------------\n");
head=first;
printf(" Original nodes: ");
for(i=0; head!= NULL; head= head->next, i++)
printf("\n%d-ith value: %d ", i, head->value);
printf("\n------------------------\n");
struct node *first_no30= delete_from_list(first, 30);
struct node *head_no30= first_no30;
printf("\n------------------------\n");
printf(" Nodes without 30: ");
for(i=0; head_no30!= NULL; head_no30= head_no30->next, i++)
printf("\n%d-ith value: %d ", i,head_no30->value);
printf("\n------------------------\n");
printf("\n------------------------\n");
printf(" Original nodes: ");
head=first;
for(i=0; head!= NULL; head= head->next, i++)
printf("\n%d-ith value: %d ", i, head->value);
printf("\n------------------------\n");
return 0;
}
struct node *delete_from_list(struct node *list, int n) {
struct node *cur, *prev;
for(cur=list, prev=NULL;
cur != NULL && cur->value !=n;
prev= cur, cur= cur->next)
;
if(cur == NULL)
return list;
if(prev== NULL)
list= list->next;
else
prev->next= cur->next;
free(cur);
return list;
}
struct node *add_to_list(struct node *list, int n) {
struct node *new_node;
new_node= malloc(sizeof(struct node));
if(new_node == NULL) {
printf("Error: malloc failed in add_to_list\n");
exit(EXIT_FAILURE);
}
new_node->value = n;
new_node->next= list;
return new_node;
}
I think that this quote
Note that add_to_list doesn't modify the list pointer. Instead, it
returns a pointer to the newly created node....Getting add_to_list to
update first, turns out to be tricky.
denotes the following.
When a new node is added to the list then all pointers to nodes (as for example the passed pointer and values of the data member next) that already exist in the list are not changed.
On the other hand, when a node is deleted then pointers to nodes (as for example the pointer that points to the deleted node or the value of the data member next of the preceding node) can be changed.
Having tried, in the comments under the OP, to teach that the plethora of pointers in the OP code was the source of the problem, there is little else one can do but demonstrate the correct use of ONE pointer to the first node of the evolving LL (and one useful pointer that can traverse the LL.)
Here is the main() function written to perform the apparently desired task.
int main( void ) {
struct node *first = NULL;
struct node *p = NULL;
// first node
p = malloc(sizeof(struct node));
p->value = 10;
p->next = first; first = p;
//second node
p = malloc(sizeof(struct node));
p->value = 20;
p->next = first; first = p;
//third node
p = malloc(sizeof(struct node));
p->value = 40;
p->next = first; first = p;
//fourth node
p = malloc(sizeof(struct node));
p->value = 30;
p->next = first; first= p;
puts( "Created nodes:" );
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
first = delete_from_list( first, 20 );
puts( "Nodes without 20:" );
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
first = delete_from_list( first, 30 );
puts( "Nodes without 30:");
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
first = delete_from_list( first, 10 );
puts( "Nodes without 10:");
for( p = first; p != NULL; p = p->next )
printf( "[%d] ", p->value );
puts( "\n------------------------" );
printf( "There are no \"original nodes\". There are only those nodes on the list." );
return 0;
}
Omitted is the verification of the success of those multiple malloc() calls. An exercise for the reader.

Getting the nth from last of the linked list

What I'm doing is that first I reversed the linked list and then actually I'm trying to get the nth value of a node. The problem is that the function isn't doing anything after it reverses the linked list and doesn't give an error for some reason.
Here's my code:
#include<stdlib.h>
#include<assert.h>
// 1. Create a linked list first
struct Node {
int data;
struct Node* next;
};
// 2. Create traversal function for linked list
void linkedListTraversal(struct Node* ptr) {
while (ptr != NULL) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
}
// 3. Write a function to get the node value from the tail of the linked list
int getNode(struct Node* head, int positionFromTail) {
int value;
struct Node* prevNode = NULL;
struct Node* currNode = head;
struct Node* nextNode;
while (currNode != NULL) {
nextNode = currNode->next;
currNode->next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
head = prevNode;
struct Node* ptr = head;
int count = 0;
while (ptr != NULL) {
if (count == positionFromTail) {
return (ptr->data);
count = count + 1;
ptr = ptr->next;
}
}
assert(0);
}
int main() {
struct Node* head;
struct Node* second;
struct Node* third;
struct Node* fourth;
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
fourth = (struct Node*)malloc(sizeof(struct Node));
head->data = 3;
head->next = second;
second->data = 2;
second->next = third;
third->data = 1;
third->next = fourth;
fourth->data = 0;
fourth->next = NULL;
linkedListTraversal(head);
printf("The value of the node is %d", getNode(head, 2));
}
Here's my output and any help will be appreciated.
3
2
1
0
You can have an infinite loop because the pointer ptr is changed only when the condition of the if statement within the loop evaluates to true
while (ptr!=NULL)
{
if (count == positionFromTail)
{
return (ptr->data);
count = count + 1;
ptr = ptr->next;
}
}
Rewrite the for loop at least for example like
while ( ptr != NULL && positionFromTail-- )
{
ptr = ptr->next;
}
if ( ptr != NULL )
{
return ptr->data;
}
else
{
// return some value
return -1;
}
Also the parameter positionFromTail shall have an unsigned integer type. Otherwise you need to check in the beginning of the function whether it has a negative value.
Pay attention to that after exiting the function your list will be broken. The pointer head in main will not be changed after calling the function but the value of the data member next of the node pointed to by the pointer and of other nodes will be changed. So in general your approach is incorrect.
There is no need to reverse the list to find an element at the given position counted from the end of the list.
For starters I would declare the function the following way
int getNode( const struct Node *head, int pos, int *data );
That is the function returns either 1 if there exists a node with the specified position or 0 otherwise. If there is a node with the specified position then the stored value is written in the dereferenced parameter data.
If the value of the parameter pos is not negative then counting of nodes starts from the head otherwise from the end of the list.
Here is a demonstration program.
#include <stdlib.h>
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
void clear( struct Node **head )
{
while (*head)
{
struct Node *current = *head;
*head = ( *head )->next;
free( current );
}
}
size_t create( struct Node **head, const int a[], size_t n )
{
clear( head );
size_t i = 0;
while (n-- && ( *head = malloc( sizeof( struct Node ) ) ) != NULL )
{
( *head )->data = *a++;
( *head )->next = NULL;
++i;
head = &( *head )->next;
}
return i;
}
FILE * display( const struct Node *head, FILE *fp )
{
for (; head != NULL; head = head->next)
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
int getNode( const struct Node *head, int pos, int *data )
{
int success = 0;
if (!( pos < 0 ))
{
while (head != NULL && pos--)
{
head = head->next;
}
if (( success = head != NULL )) *data = head->data;
}
else
{
const struct Node *current = head;
for ( ;current != NULL && pos; ++pos )
{
current = current->next;
}
while (current != NULL )
{
head = head->next;
current = current->next;
}
if (( success = pos == 0 )) *data = head->data;
}
return success;
}
int main( void )
{
struct Node *head = NULL;
const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
create( &head, a, sizeof( a ) / sizeof( *a ) );
fputc( '\n', display(head, stdout ) );
for (int i = 0, data; getNode( head, i, &data ); i++)
{
printf( "%d: %d; ", i, data );
}
putchar( '\n' );
for (int i = -1, data; getNode( head, i, &data ); i--)
{
printf( "%d: %d; ", i, data );
}
putchar( '\n' );
clear( &head );
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
0: 0; 1: 1; 2: 2; 3: 3; 4: 4; 5: 5; 6: 6; 7: 7; 8: 8; 9: 9;
-1: 9; -2: 8; -3: 7; -4: 6; -5: 5; -6: 4; -7: 3; -8: 2; -9: 1; -10: 0;

How to store the data dynamically in linked list in C?

I'm trying to store the values in the linked list dynamically.
I want the user to input the size of the linked List. Then based on the input I want to allocate the memory (i.e if Input : 3 then three nodes should be created).
If memory is allocated for nodes then I store the head node in a temp.
After that I want to store the data in list untill list comes to the end
The algorithm which I used is following
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// Printing the list
void printList(struct node *ptr)
{
int i = 1;
while(ptr != NULL)
{
printf("\n Value in Node %d : %d",i ,ptr->data);
ptr = ptr->next;
i++;
}
}
int main()
{
int n;
struct node *head;
struct node *temp;
printf("\n Enter the size of linkedList : ");
scanf("%d",&n);
head = malloc(sizeof(struct node) * n);
// Storing head in temp
temp = head;
int i = 1; // Keep track on the position of the list
while(temp != NULL) // Untill temp get to end of the list
{
printf("\n Enter the value in node %d : ", i);
scanf("%d",&temp->data);
temp = temp->next; // Assinging next list address
}
printList(head);
return 0;
}
I don't understand why it printing only one value when I'm executing it.
I don't know how wrong I was?
**OUTPUT : **
$ clang dynamicList.c -o a
$ ./a
Enter the size of linkedList : 10
Enter the value in node 1 : 9
Value in Node 1 : 9
This call of malloc
head = malloc(sizeof(struct node) * n);
allocates an uninitialized memory.
Thus this statement in the while loop
temp = temp->next;
assigns an indeterminate value to the pointer temp and using this pointer further in the loop invokes undefined behavior.
Moreover the condition in the loop
while(temp != NULL) // Untill temp get to end of the list
does not make a sense.
This declaration within the block scope of the loop
int i = 1; // Keep track on the position of the list
and the similar declaration in the function printList
int i = 1;
also do not make a sense.
You need to initialize exactly n nodes. So the loop should look like
for ( int i = 0; i < n; i++ )
{
//...
}
Also you should free all the allocated memory when the list will not be needed any more.
Pay attention to that you allocated an array of nodes. Using your approach the program can look the following way.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// Printing the list
void printList( const struct node *ptr )
{
for ( unsigned int i = 1; ptr != NULL; ptr = ptr->next )
{
printf( "Value in Node %u : %d\n", i++, ptr->data );
}
}
int main( void )
{
unsigned int n = 0;
struct node *head = NULL;
printf( "Enter the size of linkedList : " );
scanf( "%u", &n );
head = malloc( n * sizeof( struct node ) );
struct node *temp = head;
for ( unsigned int i = 0; i < n; i++ )
{
printf( "Enter the value in node %u : ", i + 1 );
scanf( "%d", &temp->data );
temp->next = i == n - 1 ? NULL : temp + 1;
++temp;
}
printList( head );
free( head );
return 0;
}
The program output might look like
Enter the size of linkedList : 10
Enter the value in node 1 : 1
Enter the value in node 2 : 2
Enter the value in node 3 : 3
Enter the value in node 4 : 4
Enter the value in node 5 : 5
Enter the value in node 6 : 6
Enter the value in node 7 : 7
Enter the value in node 8 : 8
Enter the value in node 9 : 9
Enter the value in node 10 : 10
Value in Node 1 : 1
Value in Node 2 : 2
Value in Node 3 : 3
Value in Node 4 : 4
Value in Node 5 : 5
Value in Node 6 : 6
Value in Node 7 : 7
Value in Node 8 : 8
Value in Node 9 : 9
Value in Node 10 : 10
If you indeed want to organize data as a list instead of an array then the program can look the following way
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// Printing the list
void printList( const struct node *ptr )
{
for ( unsigned int i = 1; ptr != NULL; ptr = ptr->next )
{
printf( "Value in Node %u : %d\n", i++, ptr->data );
}
}
int main( void )
{
unsigned int n = 0;
struct node *head = NULL;
printf( "Enter the size of linkedList : " );
scanf( "%u", &n );
struct node *temp;
for ( unsigned int i = 0; i < n; i++ )
{
if ( i == 0 )
{
head = malloc( sizeof( struct node ) );
temp = head;
}
else
{
temp->next = malloc( sizeof( struct node ) );
temp = temp->next;
}
printf( "Enter the value in node %u : ", i + 1 );
scanf( "%d", &temp->data );
temp->next = NULL;
}
printList( head );
while ( head != NULL )
{
temp = head;
head = head->next;
free( temp );
}
return 0;
}
The program output might look as shown for the previous demonstrative program.
When you create a new node, you should allocate the next node and after that move the current node to the next one. Also, you should pay attention to the initial state (when size is 1). You should modify your code similar to this:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
// Printing the list
void printList(struct node* ptr) {
while (ptr != NULL) {
int i = 1;
printf("\n Value in Node %d : %d", i, ptr->data);
ptr = ptr->next;
}
}
int main() {
int n;
struct node* head;
struct node* temp;
printf("\n Enter the size of linkedList : ");
scanf("%d", &n);
int i = 1; // Keep track on the position of the list
while (i <= n) // Untill temp get to end of the list
{
if (i == 1) {
head = malloc(sizeof(struct node) * n);
temp = head;
} else {
temp->next = malloc(sizeof(struct node) * n);
temp = temp->next;
}
printf("\n Enter the value in node %d : ", i);
scanf("%d", &temp->data);
++i;
}
printList(head);
return 0;
}
Also, you should free dynamically allocated memory at the end of the program to avoid memory leaks.

Unable to create and display linked list in C

I want to create integer linked list and display. Suppose there are 3 nodes with values 11,22,33 . But when I display it, its printing only 1st value i.e. 11 . What is going wrong?
NOTE : To create and display linked list , Whether head and p node variable are enough or is it must to take 3 node pointer variables . i.e. head , p and q also?
#include <stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *next;
}node;
int main()
{
int i, j, num, value;
node *p = NULL;
node *head = NULL;
printf("how many nodes\r\n");
scanf("%d",&num);
for(i = 0 ;i < num ; i++)
{
printf("enter node %d = ",i+1);
scanf("%d",&value);
p = (node *)malloc(sizeof(node));
p->data = value;
p->next = NULL;
if(head == NULL)
{
head = p;
}
}
printf("linked list formed is \r\n");
for(p = head ; p != NULL ; p = p->next)
{
printf("p->data = %d\r\n ",p->data);
}
return 0;
}
You build a forward-chained linked list in input order by constantly updating a target point on which to hang the next node.
Initially that pointer is the head pointer.
The next node will be hung on the next pointer of that previous node.
When done, the last next pointer is set to NULL and you're finished.
It may sound complicated, but utilizing a pointer-to-pointer makes the algorithm surprisingly simple, efficient, and requires no special tedious case for testing for a null head pointer that will only ever be true once. Including added error checking
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} node;
int main()
{
node *head = NULL;
node **pp = &head;
int num;
printf("how many nodes\r\n");
if (scanf("%d", &num) == 1 && num > 0)
{
for (int i=0; i<num;)
{
int value;
printf("enter node %d = ", i+1);
if (scanf("%d", &value) == 1)
{
*pp = malloc(sizeof **pp);
if (*pp == NULL)
{
perror("Failed to allocate new list node");
exit(EXIT_FAILURE);
}
// hang the new node
(*pp)->data = value;
// setup pp to hold address of next pointer
// to populate on the next iteration.
pp = &(*pp)->next;
// next node
++i;
}
else
{
int c;
while ((c = fgetc(stdin)) != EOF && c != '\n');
}
}
// terminate the list
*pp = NULL;
}
printf("linked list formed is:\n");
for (const node *p = head; p != NULL; p = p->next)
{
printf(" p->data = %d\n", p->data);
}
// free the list
while (head)
{
node *p = head;
head = head->next;
free(p);
}
return 0;
}
Sample Run
how many nodes
5
enter node 1 = 1
enter node 2 = 3
enter node 3 = 5
enter node 4 = 7
enter node 5 = 9
linked list formed is:
p->data = 1
p->data = 3
p->data = 5
p->data = 7
p->data = 9
You are just updating the head first time and not creating any links
please find the fixed code below
#include <stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *next;
}node;
int main()
{
int i, j, num, value;
node *p = NULL;
node *head = NULL;
printf("how many nodes\r\n");
scanf("%d",&num);
for(i = 0 ;i < num ; i++)
{
printf("enter node %d = ",i+1);
scanf("%d",&value);
p = (node *)malloc(sizeof(node));
p->data = value;
p->next = NULL;
// Form links
p->next = head;
head = p;
}
printf("linked list formed is \n");
for(p = head ; p != NULL ; p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
// Freeing memory to avoid mem leaks
for(p = head ; head != NULL ; head = head->next)
{
p = head;
free(p);
}
return 0;
}
You can refer to my library for a more generic implementation of link_list
A change in code by Mohammed Meraj to create the list in the correct order.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
int main()
{
int i, num, value;
node *p = NULL;
node *head = NULL;
node *q = NULL;
printf("how many nodes\r\n");
scanf("%d",&num);
for(i = 0 ;i < num ; i++)
{
printf("enter node %d = ",i+1);
scanf("%d",&value);
p = (node *)malloc(sizeof(node));
p->data = value;
p->next = NULL;
// Form links
if(!q) head = q = p;
else{ q->next = p; q = p; }
}
printf("linked list formed is \n");
for(p = head ; p != NULL ; p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
// Freeing memory to avoid mem leaks
while(head != NULL)
{
p = head;
head = head->next;
free(p);
}
return 0;
}
if you want to do the code with only head and p, it can be done too
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
int main()
{
int i, num, value;
node *p = NULL;
node *head = NULL;
printf("how many nodes\r\n");
scanf("%d",&num);
for(i = 0 ;i < num ; i++)
{
printf("enter node %d = ",i+1);
scanf("%d",&value);
if(!head){
head = (node *)malloc(sizeof(node));
head->data = value;
head->next = NULL;
p = head;
}else{
p->next = (node *)malloc(sizeof(node));
p->next->data = value;
p->next->next = NULL;
p = p->next;
}
}
printf("linked list formed is \n");
for(p = head ; p != NULL ; p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
// Freeing memory to avoid mem leaks
while(head != NULL)
{
p = head;
head = head->next;
free(p);
}
return 0;
}

Structure pointer assignment not assigning expected value - Linked Lists

I'm writing a program to reverse a linked list in C. While debugging code in gdb, after the second iteration of while loop, function,reverse, take exit.
#include <stdio.h>
#include <stdlib.h>
void insert (int number);
void print ();
struct Node {
int data;
struct Node *link;
} head, *last_node;
int count (struct Node *);
void reverse (struct Node *);
int main () {
int number, choice = 0;
while (choice != 4) {
printf ("\nChoose the action: ");
printf ("\n 1. Insert ");
printf ("\n 2. Print List ");
printf ("\n 3. Reverse");
printf ("\n 4. Exit \n");
scanf("%d", &choice);
switch (choice) {
case 1 : printf ("\nEnter number to be inserted: ");
scanf ("%d", &number);
insert (number);
break;
case 2 : printf ("\nHere is/are linked list element/s: ");
print();
break;
case 3 : printf ("\nLinked List Reversed ");
reverse(&head);
break;
case 4 :
default: exit(0);
}
}
}
void insert (int number) {
if (head.data == 0) {
head.data = number;
head.link = NULL;
last_node = &head;
} else {
struct Node *new_node;
new_node = (struct Node *) malloc (sizeof(struct Node));
new_node -> data = number;
new_node -> link = NULL;
last_node -> link = new_node;
last_node = new_node;
}
}
void print () {
struct Node *start;
start = &head;
do {
printf ("%d ", start->data);
start = start->link;
} while (start != NULL);
printf ("\n");
}
void reverse (struct Node *start) {
struct Node *temp1 = NULL, *temp2;
while (start->link != NULL) {
temp2 = start->link;
start->link = temp1;
temp1 = start;
start = temp2;
}
}
After running reverse function only first element of linked list shows.
There are several drawbacks of your approach.
The first one is that it is a bad idea to declare a global variable start.
struct Node {
int data;
struct Node *link;
} head, *last_node;
Also if it is a singly-linked list then nodes should be inserted to the beginning of the list. So the global pointer last_node is not required.
The function reverse deals with the local variable start because function parameters are local variables of functions
void reverse (struct Node *start)
The original pointer to the start node is not changed in the function because the function deals with its copy.
And the function has to check whether the passed argument is already equal to NULL.
There is a simple logic behind the reverse algorithm.
You should just insert already existent nodes as if you would do this within the function that pushes new nodes into list.
And the pointer to the start node (head) must be passed by reference using a pointer to it.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *link;
};
int push_front( struct Node **head, int data )
{
struct Node *current = malloc( sizeof( struct Node ) );
int success = current != NULL;
if ( success )
{
current->data = data;
current->link = *head;
*head = current;
}
return success;
}
void output( struct Node *head )
{
for ( ; head != NULL; head = head->link )
{
printf( "%d -> ", head->data );
}
puts( "NULL" );
}
void reverse( struct Node **head )
{
struct Node *current = *head;
*head = NULL;
while ( current != NULL )
{
struct Node *tmp = current;
current = current->link;
tmp->link = *head;
*head = tmp;
}
}
int main(void)
{
struct Node *head = NULL;
const int N = 10;
for ( int i = 0; i < N; i++ ) push_front( &head, i );
output( head );
reverse( &head );
output( head );
return 0;
}
Its output is
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> NULL
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
Of course you need to append the list implementation with a function that deletes all nodes of the list when it is not anymore required.

Resources