排序算法----快速排序(鏈表形式)


單鏈表形式實現排序算法。

這個快速排序主要利用遞歸調用。包含4個文件,頭文件QuickSort.h,fatal.h,庫函數QuickSort.c,測試文件TestQuickSort。

QuickSort.h

 

 1 typedef long ElementType;
 2 #ifndef _List_H//如果沒有編譯過
 3 #include<stdbool.h>
 4 struct Node;
 5 typedef struct Node *PtrToNode;
 6 typedef PtrToNode List;
 7 typedef PtrToNode Position;
 8 List MakeEmpty(List L);
 9 void DeleteList(List L);
10 bool IsEmpty(List L);
11 bool IsLast(Position P, List L);
12 void Insert(ElementType X, List L, Position P);
13 Position Header(List L);
14 Position First(List L);
15 Position Advance(Position P);
16 ElementType Retrieve(Position P);
17 void PrintList(const List L);
18 void SwapWithNext(Position BeforeP, List L);
19 void Qsort(List L, List tail);//快速排序核心算法
20 void QuickSort(List L);//快速排序驅動程序
21 #endif // !_List_H

 

 

 

fatal.h

1 #include<stdio.h>
2 #include<stdlib.h>
3 #define Error(Str) FatalError(Str)
4 #define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1);

庫函數QuickSort.c

 

  1 // 引用頭文件
  2 #include "QuickSort.h"
  3 #include<stdlib.h>
  4 #include "fatal.h"
  5 
  6 //結構體定義
  7 struct Node
  8 {
  9     ElementType Element;
 10     Position Next;
 11 };
 12 
 13 //初始化鏈表
 14 List MakeEmpty(List L)
 15 {
 16     if (L != NULL)
 17         DeleteList(L);//如果鏈表非空,則刪除鏈表
 18     L = malloc(sizeof(struct Node));
 19     if (L == NULL)
 20         FatalError("Out of memory!");
 21     L->Next = NULL;
 22     return L;
 23 }
 24 
 25 //刪除鏈表
 26 void DeleteList(List L)
 27 {
 28     Position P, Temp;
 29     P = L->Next;
 30     L->Next = NULL;
 31     while (P != NULL)
 32     {
 33         Temp = P->Next;
 34         free(P);
 35         P = Temp;
 36     }
 37 }
 38 
 39 //判斷鏈表是否為空
 40 bool IsEmpty(List L)
 41 {
 42     return L->Next == NULL;
 43 }
 44 
 45 //判斷當前指針P是否指向鏈表最后一個元素
 46 bool IsLast(Position P, List L)
 47 {
 48     return P->Next == NULL;
 49 }
 50 
 51 
 52 
 53 //插入元素X到位置P后面
 54 void Insert(ElementType X, List L, Position P)
 55 {
 56     Position  TmpCell;
 57     TmpCell = malloc(sizeof(struct Node));
 58     if (TmpCell == NULL)
 59         FatalError("Out of Space!!!");
 60     TmpCell->Element = X;
 61     TmpCell->Next = P->Next;
 62     P->Next = TmpCell;
 63 }
 64 
 65 //獲取鏈表頭
 66 Position Header(List L)
 67 {
 68     return L;
 69 }
 70 
 71 //獲取鏈表第一個元素的位置
 72 Position First(List L)
 73 {
 74     return L->Next;
 75 }
 76 
 77 //獲取位置P的下一個位置
 78 Position Advance(Position P)
 79 {
 80     return P->Next;
 81 }
 82 
 83 //提取位置P處結構里面的值
 84 ElementType Retrieve(Position P)
 85 {
 86     return P->Element;
 87 }
 88 
 89 //打印鏈表
 90 void PrintList(const List L)
 91 {
 92     Position P = Header(L);
 93     if (IsEmpty(L))
 94         printf("Empty list\n");
 95     else
 96     {
 97         do
 98         {
 99             P = Advance(P);
100             printf("%d ", Retrieve(P));
101         } while (!IsLast(P, L));
102         printf("\n");
103     }
104 }
105 
106 
107 //通過只調整指針來交換兩個相鄰的元素,BeforeP是要調換兩個元素的前一
108 //個指針
109 void SwapWithNext(Position BeforeP, List L)
110 {
111     Position P, AfterP;
112     if (BeforeP != NULL)
113     {
114         P = Advance(BeforeP);
115         if (P != NULL)
116         {
117             AfterP = Advance(P);
118             if (AfterP != NULL)
119             {
120                 P->Next = AfterP->Next;
121                 BeforeP->Next = AfterP;
122                 AfterP->Next = P;
123             }
124         }
125     }
126 }
127 
128 //快速排序核心算法
129 void Qsort(List head, List tail)
130 {
131     //將鏈表分成2、4、8。。。,我們只說明開始分成2兩條的情況
132     //將鏈表分成兩條,小於樞紐元的鏈表1,大於等於樞紐元的鏈表2,鏈表1已經有了頭結點head,鏈表2以樞紐元為頭結點mid
133     if (head->Next == tail || head->Next->Next == tail)
134         return;//如果鏈表是空或者只有一個元素,則停止循環
135 
136     List mid = head->Next;//指向樞紐元的指針
137     List p = head;//指向鏈表1,最后p指向鏈表1的尾元素
138     List q = mid;//指向鏈表2,最后q指向鏈表2的尾元素
139     ElementType pivot = mid->Element;//樞紐元
140     List t = mid->Next;//探測指針,指向下一個元素,查詢是大於樞紐元還是小於樞紐元
141 
142     while (t != tail)//當探測指針指向鏈表尾節點,循環結束
143     {
144         if (t->Element < pivot)//當探測指針指向的元素<樞紐元,則把該元素接到鏈表1
145             p = p->Next = t;
146         else
147             q = q->Next = t;//當探測指針指向的元素>=樞紐元,則把該元素接到鏈表2
148         t = t->Next;//不管上一個元素大小如何,都要指向下一個元素
149     }
150     //當循環完整個鏈表,然后將鏈表1和2拼接起來
151     p->Next = mid;//將小於樞紐元的鏈表1的尾節點指向樞紐元
152     q->Next = tail;//將鏈表2的尾節點指向tail
153 
154     Qsort(head, mid);//對鏈表1進行同樣的循環,當滿足113行條件,則停止這個遞歸
155     Qsort(mid, tail);//對鏈表2進行同樣的循環,當滿足113行條件,則停止這個遞歸
156     //當兩個QuickSort都滿足113行時,跳出遞歸循環,程序結束
157 }
158 
159 //快速排序驅動程序
160 void QuickSort(List L)
161 {
162     Qsort(L, NULL);//調用排序算法,第二個是NULL
163 }

 

 

 

測試文件TestQuickSort:

 

 1 #include<stdio.h>
 2 #include "QuickSort.h"
 3 #include"fatal.h"
 4 #include<time.h>
 5 
 6 int main()
 7 {
 8     long  amount;      List L; Position P;
 9     L = MakeEmpty(NULL);//初始化鏈表
10     P = L;
11     if (L == NULL) Error("Out of Space!!!");
12     printf("隨機生成多少位數:");
13     scanf_s("%d", &amount);
14     srand((unsigned)time(NULL));
15     for (long i = 0; i < amount; i++)
16     {
17         Insert(rand() % 1000000, L, P);
18         P = Advance(P);
19     }
20     //printf("排序前的結果:");
21     //PrintList(L);
22     QuickSort(L);//調用排序驅動程序
23     printf("排序后的結果:");
24     PrintList(L);
25 }

 

 

 


免責聲明!

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



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