單鏈表的快速排序

方法一:

單鏈表的快速排序和數組的快速排序在基本細想上是一致的,以從小到大來排序單鏈表爲例,都是選擇一個支點,然後把小於支點的元素放到左邊,把大於支點的元素放到右邊。但是,由於單鏈表不能像數組那樣隨機存儲,和數組的快排序相比較,還是有一些需要注意的細節:

1. 支點的選取,由於不能隨機訪問第K個元素,因此每次選擇支點時可以取待排序那部分鏈表的頭指針。

2. 遍歷量表方式,由於不能從單鏈表的末尾向前遍歷,因此使用兩個指針分別向前向後遍歷的策略實效,

    事實上,可以可以採用一趟遍歷的方式將較小的元素放到單鏈表的左邊。具體方法爲:

    1)定義兩個指針pslow, pfast,其中pslow指單鏈表頭結點,pfast指向單鏈表頭結點的下一個結點;

    2)使用pfast遍歷單鏈表,每遇到一個比支點小的元素,就和pslow進行數據交換,然後令pslow=pslow->next。

3. 交換數據方式,直接交換鏈表數據指針指向的部分,不必交換鏈表節點本身。

void sort_slist(SList* phead, SList* pend)
{
if(phead == NULL || pend == NULL) return;
if(phead == pend) return;
SList* pslow = phead;
SList* pfast = phead->next;
SList* ptemp = phead; 
while(pfast && pfast != pend->next)
{
   if(pfast->data <= phead->data) //phead作爲支點

   {
    ptemp = pslow;
    pslow = pslow->next;
    swap(pslow->data, pfast->data);
   }
   pfast = pfast->next;
}
swap(phead->data, pslow->data);

sort_slist(phead, ptemp);//ptemp爲左右兩部分分割點的前一個節點
sort_slist(pslow->next, pend);

}
方法二:

可以把待排序的鏈表拆分爲2個子鏈表。爲了簡單起見,選擇鏈表的第一個節點作爲基準,然後進行比較,比基準大節點的放入左面的子鏈表,比基準大的放入右邊的子鏈表。在對待排序鏈表掃描一遍之後,左面子鏈表的節點值都小於基準的值,右邊子鏈表的值都大於基準的值,然後把基準插入到鏈表中,並作爲連接兩個子鏈表的橋樑。然後根據左右子鏈表中節點數,選擇較小的進行遞歸快速排序,而對數目較多的則進行迭代等排序,以提高性能。

  1. /** 
  2. * 單鏈表的快排序 
  3. * author :blue 
  4. * data   :2010-4-6 
  5. */  
  6.   
  7. #include <stdio.h>  
  8. #include <stdlib.h>  
  9. #include <time.h>  
  10. //鏈表節點  
  11. struct node {  
  12.     int data;  
  13.     struct node *next;  
  14. };  
  15. //鏈表快排序函數  
  16. void QListSort(struct node **head, struct node *head);  
  17. //打印鏈表  
  18. void print_list(struct node *head) {  
  19.     struct node *p;  
  20.     for (p = head; p != NULL; p = p->next) {  
  21.         printf("%d ", p->data);  
  22.     }  
  23.     printf("/n");  
  24. }  
  25. int main(void) {  
  26.     struct node *head;  
  27.     struct node *p;  
  28.     int i = 0;  
  29.     /** 
  30.     * 初始化鏈表 
  31.     */  
  32.     head = (struct node*)malloc(sizeof(struct node));  
  33.     head->next = NULL;  
  34.     head->data = 0;  
  35.     srand((unsigned)time(NULL));  
  36.     for (i = 1; i < 11; ++i) {  
  37.         p = (struct node*)malloc(sizeof(struct node));  
  38.         p->data = rand() % 100 + 1;  
  39.         p->next = head->next;  
  40.         head->next = p;  
  41.     }  
  42.       
  43.     print_list(head);  
  44.     printf("---------------------------------/n");  
  45.     QListSort(&head, NULL);  
  46.     print_list(head);  
  47.     return 0;  
  48. }  
  49.   
  50. void QListSort(struct node **head, struct node *end) {  
  51.     struct node *right;  
  52.     struct node **left_walk, **right_walk;  
  53.     struct node *pivot, *old;  
  54.     int count, left_count, right_count;  
  55.     if (*head == end)  
  56.         return;  
  57.     do {  
  58.         pivot = *head;  
  59.         left_walk = head;  
  60.         right_walk = &right;  
  61.         left_count = right_count = 0;  
  62.         //取第一個節點作爲比較的基準,小於基準的在左面的子鏈表中,  
  63.         //大於基準的在右邊的子鏈表中  
  64.         for (old = (*head)->next; old != end; old = old->next) {  
  65.             if (old->data < pivot->data) {   //小於基準,加入到左面的子鏈表,繼續比較  
  66.                 ++left_count;  
  67.                 *left_walk = old;            //把該節點加入到左邊的鏈表中,  
  68.                 left_walk = &(old->next);  
  69.             } else {                         //大於基準,加入到右邊的子鏈表,繼續比較  
  70.                 ++right_count;  
  71.                 *right_walk = old;             
  72.                 right_walk = &(old->next);  
  73.             }  
  74.         }  
  75.         //合併鏈表  
  76.         *right_walk = end;       //結束右鏈表  
  77.         *left_walk = pivot;      //把基準置於正確的位置上  
  78.         pivot->next = right;     //把鏈表合併  
  79.         //對較小的子鏈表進行快排序,較大的子鏈表進行迭代排序。  
  80.         if(left_walk > right_walk) {  
  81.             QListSort(&(pivot->next), end);  
  82.             end = pivot;  
  83.             count = left_count;  
  84.         } else {  
  85.             QListSort(head, pivot);  
  86.             head = &(pivot->next);  
  87.             count = right_count;  
  88.         }  
  89.     } while (count > 1);   
  90. }  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章