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

Posted 新爱代

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法----快速排序(链表形式)相关的知识,希望对你有一定的参考价值。

单链表形式实现排序算法。

这个快速排序主要利用递归调用。包含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 }

 

 

 

以上是关于排序算法----快速排序(链表形式)的主要内容,如果未能解决你的问题,请参考以下文章

算法链表的快速排序和归并排序

常见的链表排序(Java版)

数据结构排序算法

数据结构排序算法

数据结构排序算法

表插入排序算法