鏈表的選擇排序

/********************************* 鏈表的排序  *******************************************/  
/* 
========================== 
 功能:選擇排序(由小到大) 
 返回:指向鏈表表頭的指針 
========================== 
 
 選擇排序的基本思想就是反覆從還未排好序的那些節點中, 
 選出鍵值(就是用它排序的字段,我們取學號num爲鍵值)最小的節點, 
 依次重新組合成一個鏈表。 
 
 我認爲寫鏈表這類程序,關鍵是理解: 
 head存儲的是第一個節點的地址,head->next存儲的是第二個節點的地址; 
 任 意一個節點p的地址,只能通過它前一個節點的next來求得。 
 
單向鏈表的選擇排序圖示: 
---->[1]---->[3]---->[2]...----> [n]---->[NULL](原鏈表) 
head   1->next  3->next  2->next   n->next 
 
---->[NULL](空鏈表) 
first 
tail 
---->[1]---->[2]---->[3]...---->[n]---->[NULL](排序後鏈表) 
first   1->next  2->next  3->next   tail->next 
 
1、先在原鏈表中找最小的,找到一個後就把它放到另一個空的鏈表中; 
2、空鏈表中安放第一個進來的節點,產生一個有序鏈表,並且讓它在原鏈表中分離出來(此時要注意原鏈表中出來的是第一個節點還是中間其它節點); 
3、繼續在原鏈表中找下一個最小的,找到後把它放入有序鏈表的尾指針的next,然後它變成其尾指針; 
*/  
struct student *SelectSort(struct student *head)  
{  
    struct student *pfirst;      /* 排列後有序鏈的表頭指針 */  
    struct student *ptail;       /* 排列後有序鏈的表尾指針 */  
    struct student *pminBefore;  /* 保留鍵值更小的節點的前驅節點的指針 */  
    struct student *pmin;        /* 存儲最小節點   */  
    struct student *p;           /* 當前比較的節點 */  
   
    pfirst = NULL;  
    while (head != NULL)         /*在鏈表中找鍵值最小的節點。*/  
    {  
    /* 注意:這裏for語句就是體現選擇排序思想的地方 */  
        for (p = head, pmin = head; p->next != NULL; p = p->next) /*循環遍歷鏈表中的節點,找出此時最小的節點。*/  
        {  
            if (p->next->num < pmin->num) /*找到一個比當前min小的節點。*/  
            {  
                pminBefore = p;           /*保存找到節點的前驅節點:顯然p->next的前驅節點是p。*/  
                pmin       = p->next;     /*保存鍵值更小的節點。*/  
            }  
        }  
    
    /*上面for語句結束後,就要做兩件事;一是把它放入有序鏈表中;二是根據相應的條件判斷,安排它離開原來的鏈表。*/  
      
        /*第一件事*/  
        if (pfirst == NULL)     /* 如果有序鏈表目前還是一個空鏈表                      */  
        {  
            pfirst = pmin;      /* 第一次找到鍵值最小的節點。                          */  
            ptail  = pmin;      /* 注意:尾指針讓它指向最後的一個節點。                */  
        }  
        else                    /* 有序鏈表中已經有節點                                */  
        {  
            ptail->next = pmin; /* 把剛找到的最小節點放到最後,即讓尾指針的next指向它。*/  
            ptail = pmin;       /* 尾指針也要指向它。                                  */  
        }  
  
        /*第二件事*/  
        if (pmin == head)        /* 如果找到的最小節點就是第一個節點                    */  
        {  
            head = head->next;   /* 顯然讓head指向原head->next,即第二個節點,就OK       */  
        }  
        else /*如果不是第一個節點*/  
        {  
            pminBefore->next = pmin->next; /*前次最小節點的next指向當前pmin的next,這樣就讓pmin離開了原鏈表。*/  
        }  
    }  
  
    if (pfirst != NULL)     /*循環結束得到有序鏈表first                */  
    {  
        ptail->next = NULL; /*單向鏈表的最後一個節點的next應該指向NULL */   
    }  
    head = pfirst;  
    return head;  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章