1. 程式人生 > >連結串列排序——插入排序(純C語言版)

連結串列排序——插入排序(純C語言版)

/*
==========================
 功能:直接插入排序(由小到大)
 返回:指向連結串列表 頭的指標
==========================
*/
/*
 直接插入排序的基本思想就是假設連結串列的前面n-1個節點是已經按鍵值
 (就是用它排序的欄位,我們取學號num為鍵值)排好序的,對於節點n在
 這個序列中找插入位置,使得n插入後新序列仍然有序。按照這種思想,依次
 對連結串列從頭到尾執行一遍,就可以使無序連結串列變為有序連結串列。
 
單向連結串列的直接插入排序圖示:
---->[1]---->[3]----> [2]...---->[n]---->[NULL](原連結串列)
head   1->next  3->next  2->next   n->next

---->[1]---->[NULL](從原連結串列中取第1個節點作為只有一個節點的有序連結串列)
head
圖11

---->[3]---->[2]...---->[n]---->[NULL](原連結串列剩下用於直接插入排序的節點)
first   3->next  2->next   n->next
圖12

---->[1]---->[2]---->[3]...---->[n]---->[NULL](排序後連結串列)
head   1->next  2->next  3->next   n->next

圖13:有N個節點的連結串列直接插入排序

1、先在原連結串列中以第一個節點為一個有序連結串列,其餘節點為待定節點。
2、從圖12連結串列中取節點,到圖11連結串列中定位插入。
3、上面圖示雖說畫了兩條連結串列,其實只有一條連結串列。在排序中,實質只增加了一個用於指向剩下需要排序節點的頭指標first罷了。
   這一點請讀者務必搞清楚,要不然就可能認為它和上面的選擇排序法一樣了。
*/
struct student *InsertSort(struct student *head)
{
    struct student *first; /*為原連結串列剩下用於直接插入排序的節點頭指標*/
    struct student *t; /*臨時指標變數:插入節點*/
    struct student *p; /*臨時指標變數*/
    struct student *q; /*臨時指標變數*/

    first = head->next; /*原連結串列剩下用於直接插入排序的節點連結串列:可根據圖12來理解。*/
    head->next = NULL; /*只含有一個節點的連結串列的有序連結串列:可根據圖11來理解。*/

    while (first != NULL) /*遍歷剩下無序的連結串列*/
    {
        /*注意:這裡for語句就是體現直接插入排序思想的地方*/
        for (t = first, q = head; ((q! = NULL) && (q->num < t->num)); p = q, q = q->next); /*無序節點在有序連結串列中找插入的位置*/
    
    /*退出for迴圈,就是找到了插入的位置*/
    /*注意:按道理來說,這句話可以放到下面註釋了的那個位置也應該對的,但是就是不能。原因:你若理解了上面的第3條,就知道了。*/
        first = first->next; /*無序連結串列中的節點離開,以便它插入到有序連結串列中。*/ 
  
        if (q == head) /*插在第一個節點之前*/
        {
            head = t;
        }
        else /*p是q的前驅*/
        {
            p->next = t;
        }
        t->next = q; /*完成插入動作*/
        /*first = first->next;*/
    }
    return head;
}