Search code examples
csortinglinked-listinfinite-loopinsertion-sort

Insertion Sort on Linked List in C


I am trying to perform Insertion Sort on linked list in C using following function, it gets stuck in a infinite loop. I debugged the code and found out that it works for the first pass and gets stuck in infinite loop in the second pass.

void insertion_sort()//Insertion Sort function
{
    struct Node *p = root->next;

    struct Node *a = NULL, *b = NULL;

    while(p != NULL)
    {
        a = root;

        while(a != p)
        {
            b = a;
            a = a->next;
        }

        if(b != NULL)
            b->next = a->next;
        a->next = NULL;

        struct Node *q = root;
        struct Node* r = NULL;

        while(p->data > q->data)
        {
            r = q;
            q = q->next;
        }
        p->next = q;
        if(r != NULL)
            r->next = p;

        p = p->next;
    }

}

Solution

  • For starters it is a bad idea when a function depends on a global variable. In case of your program it means for example that you can not have two lists in one program.

    I do not see where the pointer root is changed in the function insertion_sort. So even if all other code is valid nevertheless the function is incorrect because it does not change the pointer root when the value of the pointed node is unordered.

    I can suggest the following solution shown in the demonstrative program below.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    struct Node
    {
        int data;
        struct Node *next;
    };
    
    int push_front( struct Node **head, int data )
    {
        struct Node *node = malloc( sizeof( struct Node ) );
        int success = node != NULL;
        
        if ( success )
        {
            node->data = data;
            node->next = *head;
            
            *head = node;
        }
        
        return success;
    }
    
    void insertion_sort( struct Node **head )
    {
        for ( struct Node **current = head; *current != NULL; )
        {
            struct Node **sorted = head;
            
            while ( *sorted != *current && !( ( *current )->data < ( *sorted )->data ) )
            {
                sorted = &( *sorted )->next;
            }
            
            if ( *sorted != *current )
            {
                struct Node *tmp = *current;
                *current = ( *current )->next;
                tmp->next = *sorted;
                *sorted = tmp;
            }
            else
            {
                current = &( *current )->next;
            }
        }
    }
    
    FILE * output( struct Node *head, FILE *fp )
    {
        for ( ; head != NULL; head = head->next )
        {
            fprintf( fp, "%d -> ", head->data );
        }
        
        fputs( "null", fp );
        
        return fp;
    }
    
    int main(void) 
    {
        enum { N = 13 };
        
        struct Node *head = NULL;
        
        srand( ( unsigned int )time( NULL ) );
        
        for ( int i = 0; i < N; i++ )
        {
            push_front( &head, rand() % N );    
        }
        
        fputc( '\n', output( head, stdout ) );
        
        insertion_sort( &head );
        
        fputc( '\n', output( head, stdout ) );
        
        return 0;
    }
    

    The program output might look like

    1 -> 12 -> 0 -> 4 -> 0 -> 12 -> 3 -> 7 -> 12 -> 2 -> 5 -> 9 -> 7 -> null
    0 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 7 -> 7 -> 9 -> 12 -> 12 -> 12 -> null