Thread: Selection Sort on linked list

  1. #16
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Example code for list selection sort via node swapping. For 65536 nodes, it takes about 9 seconds, versus the bubble sort time of 17.5 seconds, versus the less than 1/32 of a second for merge / array sort.

    Code:
    typedef unsigned long long UI64;
    
    typedef struct NODE_{
    struct NODE_ * next;
    UI64 data;
    }NODE, *PNODE;
    
    NODE * SortList(NODE * pList)
    {
    NODE **ppNew = &pList;                          /* used to traverse sorted list */
    NODE **ppSml;                                   /* ptr to ptr to smallest node */
    NODE **ppCur;                                   /* head or previous node */
    NODE *pCur;                                     /* current node */
    NODE *pTmp;
    
        if(pList == NULL)                           /* check for NULL list */
            return(pList);
        while((*ppNew)->next != NULL){              /* while not at end list */
            ppSml = ppNew;                          /*   find smallest node */
            ppCur = &((*ppNew)->next);
            while(NULL != (pCur = *ppCur)){
                if(pCur->data < (*ppSml)->data)
                    ppSml = ppCur;
                ppCur = &((*ppCur)->next);
            }
    /*  for adjacent nodes, 3 pointers are rotated and the order of swaps matters */
            if(*ppNew != *ppSml){                   /* if not the same node */
                pTmp = *ppNew;                      /*     swap node ptrs */
                *ppNew = *ppSml;
                *ppSml = pTmp;
                pTmp = (*ppNew)->next;              /*     swap next ptrs */
                (*ppNew)->next = (*ppSml)->next;
                (*ppSml)->next = pTmp;
            }
            ppNew = &((*ppNew)->next);              /*   advance ppNew */
        }    
        return(pList);
    }

  2. #17
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by rcgldr
    Selection sort on arrays performs swaps on elements as it sorts the data. For swapping nodes in a single linked list:
    (...)
    The alternative is to use the same approach as before (and mentioned above): the sorted list starts off empty, the original list is scanned to find the smallest node, that node is removed from the original list and appended to the sorted list, repeating until the original list is empty.
    The thing is, this is the essence of selection sort. It applies to arrays too (i.e., think of "list" as "sequence" rather than "linked list"). The whole business of swapping for array implementations is to make it an in-place sort. If one were implementing selection sort where the result was a sorted copy of the original array, no swaps would be needed, so I do not see why one would bother with swapping for a linked list implementation unless it was simpler or more efficient, but I do not think either is the case.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #18
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by laserlight View Post
    selection sort ... swapping
    Swapping is used in the wiki example

    Selection sort - Wikipedia, the free encyclopedia

    so I just wanted to do the same. As mentioned before, instead of swapping, I could remove the node from the original list and append to a sorted list (that starts off as an empty list). The code for finding the smallest node would be almost the same, except that the swap stops when there's one node left, and the remove - append would stop when there are zero nodes left. The code to do a remove - append would be smaller and faster the code to do a swap, but almost of the time is spent searching for the smallest node.

    The bubble sort and the selection sort are not efficient. A merge sort using an array of pointers, which is what is used in Microsoft's version of std::list::sort, takes less than 1/32 of a second to sort 65536 nodes, while the bubble sort was worst at 17.9 seconds (in my previous posts I mistakenly listed it at 17.5 seconds), while the example selection sort with swaps takes about 9 seconds.

  4. #19
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by rcgldr
    Swapping is used in the wiki example

    Selection sort - Wikipedia, the free encyclopedia

    so I just wanted to do the same.
    For an in-place array implementation. For a linked list, the example does not use swapping.

    Quote Originally Posted by rcgldr
    As mentioned before, instead of swapping, I could remove the node from the original list and append to a sorted list (that starts off as an empty list).
    Yes, that's what I suggested in post #2, and it was also your first suggestion in post #12.

    Quote Originally Posted by rcgldr
    The code for finding the smallest node would be almost the same, except that the swap stops when there's one node left, and the remove - append would stop when there are zero nodes left.
    There are no swaps in this version, though I think you meant "search".

    Quote Originally Posted by rcgldr
    The code to do a remove - append would be smaller and faster the code to do a swap, but almost of the time is spent searching for the smallest node.
    Yes, but I was puzzled by the suggestion to mimic the typical approach for an array implementation because it just does not feel "natural" when linked lists are involved.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #20
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by rcgldr View Post
    remove the node from the original list and append to a sorted list (that starts off as an empty list).
    Quote Originally Posted by laserlight View Post
    Yes, that's what I suggested in post #2, and it was also your first suggestion in post #12.
    and it was also the way I implemented the example bubble sort for linked list in another thread created by the original poster.

    Quote Originally Posted by rcgldr View Post
    The swap stops when there's one node left, and the remove - append would stop when there are zero nodes left.
    Quote Originally Posted by laserlight View Post
    There are no swaps in this version, though I think you meant "search".
    I meant the "swap version" versus the "remove - append version".

    Quote Originally Posted by laserlight View Post
    I was puzzled by the suggestion to mimic the typical approach for an array implementation because it just does not feel "natural" when linked lists are involved.
    I had the impression that the original poster wanted to see a swap version, but after re-reading this thread, maybe he just wanted better example of the selection sort.

  6. #21
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by rcgldr
    after re-reading this thread, maybe he just wanted better example of the selection sort.
    Yeah, that is how I interpreted it.

    I received this private message:
    Quote Originally Posted by Sankait Laroiya
    You replied my selection sort on linked list thread and posted a code. In that code, second structure only keeps track of the first structure's head and tail?
    No, the second structure keeps track of the linked list's head and tail. The first structure models a node. A linked list is more than just a node.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #22
    Registered User
    Join Date
    Sep 2014
    Posts
    74
    from 'Keeps track of the first structure' I meant that it keeps track of original list's head and tail. Thanks.

  8. #23
    Registered User
    Join Date
    Sep 2014
    Posts
    74
    Okay, here is the finished code, use laserlight's guidance and his code and modified as per my needs.:
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    
    int menu(void);
    void create(int num2);
    
    
    
    int flag = 0;    // NODE COUNTER
    
    struct number
    {
        int num;
        struct number *next;
    };
    
    struct number *first=NULL;
    struct number *current=NULL;
    struct number *new_node=NULL;
    struct number *sort_list=NULL;
    struct number *list=NULL;
    struct number *prev=NULL;
    
    void display(struct number *start);
    struct number *smallest_no(struct number *spy);
    int main(void)
    {
    
        int choice,num2,x;
        printf("Welcome!\n\n");
    
        choice = menu();   // PROMPT FOR CHOICE
    
        while(choice != 3)
        {
            switch(choice)
            {
            case 1:
                {
                    printf("Number to stuff in the list: ");
                    scanf("%d", &num2);
                    create(num2);
    
                    choice = menu();
    
                    break;
                }
            case 2:
                {
                    display(first);
                    putchar('\n');
                    choice = menu();
                    break;
                }
    
            case 4:
                {
                    for(x=0;x<flag;x++)
                    {
                        sort_list = smallest_no(first);
                        if(list)
                        {
                            prev->next=sort_list;
                            prev=sort_list;
                        }
                        else
                        {
                            list = sort_list;
                            prev=list;
                        }
    
                    }
                    display(list);
                    list=NULL;
                    choice = menu();
                    break;
                }
    
    
            default:
                printf("Invalid Choice!\n\n");
                choice = menu();
                break;
            }
        }
        printf("Bye!\n\a");
        exit(0);
    }
    
    
    int menu(void)
    {
        int choice;
        printf("=== Menu === \n"); // MENU FOR CHOOSING
        printf("1 - Create Linked List OR append node in the end of current list.\n\
    2 - Display the list.\n\
    3 - Quit.\n4 - Sort the current list.\n===========\n\n");
        printf("Please enter your choice: ");
        scanf("%d", &choice);
        putchar('\n');
        return(choice);
    }
    
    void create(int num2)
    {
        if(first==NULL)       // IF THERE IS NO FIRST NODE IN THE LINKED LIST
        {                     // AND PUT THE NUMBER INPUT INTO THE NODE
            first=malloc(sizeof(struct number));
            if(first==NULL)
            {
                printf("ERROR");
                exit(0);
            }
    
            first->num = num2;
            first->next=NULL;
            current=first;
            flag = 1;
        }
        else
        {
            current=first;                 // TRAVERSE THE LINKED LIST FROM FIRST
            while(current->next != NULL)   // NODE TO THE LAST NODE
            {
                current=current->next;
            }
            new_node=malloc(sizeof(struct number));
            if(new_node==NULL)
            {
                printf("ERROR");
                exit(0);
            }
    
            current->next = new_node;     // LAST NODE IS NOW NEWLY CREATED NODE
            current=new_node;             // AND PUT THE NUMBER INPUT INTO THE NODE
            current->num= num2;
            current->next=NULL;
            flag++;                        // NODE NUMBER INCREASED
    
    
        }
    }
    
    void display(struct number *start)
    {
        if(start == NULL)
        {
            printf("No List to display!!!\n");     // LIST IS EMPTY
        }
        else
        {
            printf("Here is the list: \n");
            current=start;
            while(current != NULL)
            {
                printf("%d\t",current->num);
                current=current->next;
            }
            putchar('\n');
            putchar('\n');
            printf("TOTAL NUMBER OF NODES: %d\n", flag);
            putchar('\n');
        }
    }
    
    struct number *smallest_no(struct number *spy)
    {
        struct number *smallest = spy;
        if(smallest)
        {
            struct number *before_smallest=NULL;
            struct number *previous = smallest;
            struct number *with= smallest->next;
            while(with)
            {
                if(with->num < smallest->num)
                {
                    smallest= with;
                    before_smallest=previous;
                }
                previous=with;
                with=with->next;
            }
    
            if(before_smallest)
            {
                before_smallest->next = smallest->next;
            }
            else
            {
                first=smallest->next;
            }
    
            if(smallest->next)
            {
                smallest->next=NULL;
            }
            else
            {
                current=before_smallest;
            }
    
    }
    return(smallest);
    }
    laserlight could you please tell me, in your code (last post on the first page of this thread),how are you supposed to get the tail of the original list. I couldn't get that so I took the original list's tail and head (named current and first in the code,respectively).
    Thanks.

  9. #24
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by Sankait Laroiya
    I don't know merge sort yet
    I started another thread for merge - array for link list sort.

    merge - array sort on linked list

    The merge part is in the function MergeLists(), which shouldn't be too difficult to understand.

  10. #25
    Registered User
    Join Date
    Sep 2014
    Posts
    74
    Quote Originally Posted by rcgldr View Post
    I started another thread for merge - array for link list sort.

    merge - array sort on linked list

    The merge part is in the function MergeLists(), which shouldn't be too difficult to understand.
    Thanks rcgldr, I was eventually going to ask this question sometime later.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with selection sort for singly linked lists
    By mhroseh in forum C Programming
    Replies: 1
    Last Post: 02-24-2013, 11:51 AM
  2. Selection Sort Link List
    By Chanakya in forum C++ Programming
    Replies: 5
    Last Post: 02-11-2013, 09:32 PM
  3. Replies: 5
    Last Post: 05-29-2011, 01:23 PM
  4. Replies: 26
    Last Post: 07-05-2010, 10:43 AM
  5. Replies: 2
    Last Post: 01-17-2009, 10:48 PM