why insertion is not working in my link-list

Viewed 47

I am learning linked list Here, I am trying to add node at the first so, I made a structure function to add but i dont know why its not working its only giving this output without adding

7 11 66 After insretion 7 11 66

and also please tell me is there any way to insert element on linked list.

// inserting element on first
#include<stdio.h>
#include<stdlib.h>

struct Node
{
    int data;
    struct Node * next;
};

void link_list_tranversal(struct Node *ptr){
    while (ptr!=NULL)
    {
        printf("%d\n",ptr->data);
        ptr=ptr->next;
    }
    
   
}


struct Node * insert_at_first(struct Node *head,int data){
    struct Node *ptr=(struct Node *)malloc(sizeof(struct Node));
    ptr->next=head;
    ptr->data=data;
    return ptr;
}

int main(){
    struct Node*head;
    struct Node*second;
    struct Node*third;
    head =(struct Node *) malloc(sizeof(struct Node));
    second =(struct Node *) malloc(sizeof(struct Node));
    third =(struct Node *) malloc(sizeof(struct Node));
   // linking first and secend node
    head ->data=7;
    head->next=second;
    // linking secend and third node
    second->data=11;
    second->next=third;
    // terminate the list at the third
    third->data=66;
    third->next=NULL;
    link_list_tranversal(head);

    insert_at_first(head,56);
    printf("After insretion\n ");
    link_list_tranversal(head);
    return 0;
}
4 Answers

After insert_at_first(head,56);, you've created a new node, but head is now pointing to the second node in the list and you have lost track of the newly created node. Simplest fix is to do: head = insert_at_first(head,56);. You can also pass &head and let the function update head.

You need to update the pointer you are storing in head after calling insert_at_first.

// inserting element on first
#include<stdio.h>
#include<stdlib.h>

struct Node
{
    int data;
    struct Node * next;
};

void link_list_tranversal(struct Node *ptr){
    while (ptr!=NULL)
    {
        printf("%d\n",ptr->data);
        ptr=ptr->next;
    }
    
   
}


struct Node * insert_at_first(struct Node *head,int data){
    struct Node *ptr=(struct Node *)malloc(sizeof(struct Node));
    ptr->next=head;
    ptr->data=data;
    return ptr;
}

int main(){
    struct Node*head;
    struct Node*second;
    struct Node*third;
    head =(struct Node *) malloc(sizeof(struct Node));
    second =(struct Node *) malloc(sizeof(struct Node));
    third =(struct Node *) malloc(sizeof(struct Node));
   // linking first and secend node
    head ->data=7;
    head->next=second;
    // linking secend and third node
    second->data=11;
    second->next=third;
    // terminate the list at the third
    third->data=66;
    third->next=NULL;
    link_list_tranversal(head);

    head = insert_at_first(head,56);
    printf("After insretion\n ");
    link_list_tranversal(head);
    return 0;
}

Output:

7
11
66
After insretion
 56
7
11
66

A common approach when learning is to add more code and then add more.

Below is the equivalent to your entire program, but done with far fewer lines of code (but lots of comments.)

Please read this and think about what and why of each line.

#include <stdio.h>
#include <stdlib.h>

typedef struct Node { // Using 'typedef' saves LOTS of typing (and reading)
    int data; // for now, just one integer
    struct Node *next;
} node_t; // conventional naming of a 'type' with "_t" suffix

int mmain() {
    int data[] = { 66, 11, 7, 56 }; // your data in compact form

    node_t *head = NULL; // ALWAYS initialise variable. Don't let random values happen
    for( int i = 0; i < sizeof data/sizeof data[0]; i++ ) { // loop to create LL
        // use 'calloc()'. explained below
        // do not cast the return pointer from malloc/calloc
        node_t *pn = calloc( 1, sizeof *pn );

        // malloc/calloc can fail. Halt processing immediately.
        if( pn == NULL ) {
            fprintf( stderr, "panic! calloc failed.\n" );
            exit( 1 );
        }
        pn->data = data[i]; // for now, just one integer

        pn->next = head; // two lines of code "prepend" the new node
        head = pn;

        // traverse here showing growth
        for( pn = head; pn; pn = pn->next )
            printf( "%d  ", pn->data );
        putchar( '\n' );
    }

    // Avoid memory leaks
    // Don't forget to release heap memory when no longer needed.
    while( head ) {
        node_t *pn = head; // node to be free'd
        head = head->next; // remember next
        free( pn ); // OFF WITH ITS HEAD! 
    }

    return 0;
}

Output

66
11  66
7  11  66
56  7  11  66

I recommend using calloc() over malloc() when developing code that will grow. Right now the payload carried by each node is a single integer. In the thick of it, it is possible to add more elements to the node structure (bigger payload) yet omit setting every one of the new elements to a known value. Using calloc() insures that all bytes will consistently be initialised to null. Then, when testing, you get consistent behaviour (working or not), making it easier to track down bugs.

Notice that "prepending" to a LL is too trivial an operation to "break out" to its own function. "Appending" is not much more difficult, but may justify a function according to your tastes.

Here is the same code again, without comments, for comparison.

typedef struct Node {
    int data;
    struct Node *next;
} node_t;

int main() {
    int data[] = { 66, 11, 7, 56 };

    node_t *head = NULL;
    for( int i = 0; i < sizeof data/sizeof data[0]; i++ ) {
        node_t *pn = calloc( 1, sizeof *pn );
        if( pn == NULL ) {
            fprintf( stderr, "panic! calloc failed.\n" );
            exit( 1 );
        }
        pn->data = data[i];
        pn->next = head;
        head = pn;

        // traversal for debugging
        for( pn = head; pn; pn = pn->next )
            printf( "%d  ", pn->data );
        putchar( '\n' );
    }

    while( head ) {
        node_t *pn = head;
        head = head->next;
        free( pn );
    }

    return 0;
}

Even if the program creates new nodes at different locations, you must consider the payload. Don't write a trivial insert() function that adjusts two pointers but receives 27 parameters in the function call.

The function insert_at_first returns a new value of the pointer that points to the head node. You need to assign the returned value to the pointer head to update it

head = insert_at_first(head,56);

Also there is no great sense to allocate nodes in main when you already have the function insert_at_first

You could initially write for example

struct Node *head = NULL;

head = insert_at_first( head, 66 );
head = insert_at_first( head, 11 );
head = insert_at_first( head, 7 );
head = insert_at_first( head, 56 );

Also as the function link_list_tranversal does not change the outputted list then its parameter should be declared with qualifier const

void link_list_tranversal( const struct Node *ptr );

Pay attention to that this function definition

struct Node * insert_at_first(struct Node *head,int data){
    struct Node *ptr=(struct Node *)malloc(sizeof(struct Node));
    ptr->next=head;
    ptr->data=data;
    return ptr;
}

is not good because the function will invoke undefined behavior if memory for a node will not allocated successfully.

It is better to declare and define the function the following way

int insert_at_first( struct Node **head, int data )
{
    struct Node *ptr = malloc( *ptr );
    int success = ptr != NULL;

    if ( success )
    { 
       ptr->next = *head;
       ptr->data = data;
       *head = ptr;
    }

    return success;
}

And the function can be called like for example

struct Node *head = NULL;

insert_at_first( &head, 66 );

or

struct Node *head = NULL;

if ( !insert_at_first( &head, 66 ) )
{
    puts( "Error. No enough memory" );
} 
Related