單向鏈表排序


 一、冒泡排序簡述

1、概念

  冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。
  它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越大的元素會經由交換慢慢“浮”到數列的頂端。

2、實例分析

  以數組為例進行說明:
  數組a[4] = {4,3,2,1}

  從前向后依次比較兩個元素的大小,如果順序錯誤就交換它們。經過這樣一輪,最大的元素就被交換到了數組的頂端,好像是最大的元素“浮”上去一樣。經過這樣一輪,最后的一個元素的已經確定。a[4] = {3,2,1,4}

  再次重復上邊的操作,只不過因為上一輪最后一個元素已經確定,所以這一次比較的終點(以此為界,不能超過此界)就是上一輪的最后一個元素。也就是,第二輪的比較中,數組最后一個元素沒有參與比較。第二輪比較中的最后一個元素是倒數第二個元素。經過這樣一輪比較,倒數第二個元素也被確定。a[4] = {2,1,3,4}

  重復這樣的操作,直到數組的第二個元素被確定。因為除了第一個元素外,所有的元素都被鎖定,所以第一個元素實際上也被確定。到此為止,排序完成。a[4] = {1,2,3,4}

3、冒泡排序的關鍵
<1> 每經過一輪的排序,一個最大的元素被“浮”到對應的位置。隨之,下一次比較的終點也需要向前移一個元素。
<2> 當正數第二個元素被確定的時候,冒泡排序完成。

二、冒泡法應用於單向鏈表排序

1、實例展示

① 初始鏈表

② 第一輪排序

 

③ 第二輪排序

④ 第三輪排序

2、算法流程圖

3、源碼以及測試

  1 #include <stdio.h>
  2 #include <malloc.h>
  3 
  4 /* 排序狀態取值表 */
  5 typedef enum
  6 {
  7     SORT_OK,    /* 排序成功標志 */
  8     SORT_ERR    /* 排序失敗標志 */
  9 }SORTSTATE;        
 10 
 11 /* 接點結構體 */
 12 struct node{
 13     struct node * pnext;
 14     unsigned int value;
 15 };
 16 
 17 typedef struct node Node;
 18 
 19 SORTSTATE sort(Node * * chainhead);
 20 
 21 /** @函數功能:測試單向鏈表排序功能
 22   * @輸入參數:無
 23   * @輸出參數:無用
 24   */
 25 int main(void)
 26 {
 27     Node * head,* p;
 28     SORTSTATE status;
 29 
 30     /* 構建單向鏈表 */
 31     p = (Node *)malloc(sizeof(Node));
 32     head = p;                                    /* 保存鏈表頭部 */
 33     p->value = 5;
 34     p->pnext = (Node *)malloc(sizeof(Node));
 35 
 36     p = p->pnext;
 37     p->value = 97;
 38     p->pnext = (Node *)malloc(sizeof(Node));
 39 
 40     p = p->pnext;
 41     p->value = 7;
 42     p->pnext = (Node *)malloc(sizeof(Node));
 43 
 44     p = p->pnext;
 45     p->value = 65;
 46     p->pnext = (Node *)malloc(sizeof(Node));
 47 
 48     p = p->pnext;
 49     p->value = 12;
 50     p->pnext = (Node *)malloc(sizeof(Node)); 
 51 
 52     p = p->pnext;
 53     p->value = 1;
 54     p->pnext = NULL;                            /* 鏈尾初始化為空 */
 55 
 56     /* 打印鏈表的內容 */
 57     p = head;
 58     while(p != NULL){
 59         printf("%4d",p->value);
 60         p = p->pnext;
 61     }
 62     printf("\n");
 63 
 64     /* 鏈表排序 */
 65     status = sort(&head);
 66     if(status == SORT_ERR){
 67         printf("Chain is wrong!\n");
 68     }
 69     
 70     /* 打印鏈表的內容 */
 71     p = head;
 72     while(p != NULL){
 73         printf("%4d",p->value);
 74         p = p->pnext;
 75     }
 76     printf("\n");
 77 
 78     return 0;
 79 }
 80 
 81 
 82 /** @函數功能:單向鏈表排序
 83   * @輸入參數:指向鏈表頭部的指針
 84   *        注意:指向指針的指針可以修改指針的指向
 85   * @輸出參數:SORTSTATE 排序成功與否狀態
 86   */
 87 SORTSTATE sort(Node * * chainhead)
 88 {
 89     Node * head,                                    /* 當前比較接點的上一個接點 */
 90          * first,                                    /* 當前比較接點 */
 91          * second,                                    /* 當前參與比較的另一個接點 */
 92          * end;                                        /* 當前比較接點的終點
 93                                                      * 終點意味着從終點開始往后的
 94                                                      * 鏈表排序已經確定,只需要將
 95                                                      * 終點前的所有接點按照冒泡法
 96                                                      * 排序,排序就將完成。
 97                                                      */
 98 
 99     if(*chainhead == NULL)                            /* 鏈表是否為空 */
100         return SORT_ERR;
101     if((*chainhead)->pnext == NULL)                    /* 鏈表是否就只有一個接點 */
102         return SORT_OK;
103 
104     end = NULL;                                        /* 第一輪冒泡排序的終點接點值為NULL */
105 
106     /* 冒泡法排序,可能有很多輪次 */
107     while(end != (*chainhead)->pnext){                /* 如果排序的終點等於接點的第二個地址,
108                                                      * 也就是說從第二個接點開始所有的接點
109                                                      * 都已經按照從小到大的順序確定了位置。
110                                                      * 顯然,剩下的唯一一個“第一接點”位置
111                                                      * 也就確定了。所有排序全部完成。
112                                                      */
113 
114         /* 首先比較位於頭部的兩個接點,由於位於頭部,
115          * 與其他接點不一樣,需要放在循環外邊,單獨處理。
116          */
117         first =   *chainhead;                        /* 第一個比較接點是鏈表頭部指向的接點 */
118         second = first->pnext;                        /* 第二個比較接點是緊鄰的第二個接點 */
119         
120         /* 是否需要更改鏈表的連接順序 */
121         if(first->value > second->value){            
122             *chainhead = second;                    /* 更改鏈表頭部的指向 */    
123             /* 重新連接鏈表,就相當於對鏈表排序 */
124             first->pnext = second->pnext;            
125             second->pnext = first;            
126         }
127 
128         /* 移動比較接點到下兩個接點 */
129         head = *chainhead;                            /* 當前比較接點的上一個接點則是頭部接點 */
130         first = head->pnext;                        /* 當前比較接點 */
131         second = first->pnext;                        /* 當前參與比較的另一個接點 */
132         
133         while(second != end)                        /* 此輪的比較是否結束 */
134         {
135             /* 是否需要更改鏈表的連接順序 */
136             if(first->value > second->value){    
137                 /* 重新連接鏈表,就相當於對鏈表排序 */
138                 head->pnext = second;    
139                 first->pnext = second->pnext;
140                 second->pnext = first;
141                 
142             }
143             /* 移動比較接點到下兩個接點 */
144             head = head->pnext;
145             first = head->pnext;
146             second = first->pnext;
147         }
148 
149         end = first;                                /* 一輪排序完成,結束接點位置上移一個 */
150     }
151 
152     return SORT_OK;                                    /* 排序成功 */

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM