单链表形式实现排序算法。
这个快速排序主要利用递归调用。包含4个文件,头文件QuickSort.h,fatal.h,库函数QuickSort.c,测试文件TestQuickSort。
QuickSort.h
typedef long ElementType; #ifndef _List_H//如果没有编译过 #include<stdbool.h> struct Node; typedef struct Node *PtrToNode; typedef PtrToNode List; typedef PtrToNode Position; List MakeEmpty(List L); void DeleteList(List L); bool IsEmpty(List L); bool IsLast(Position P, List L); void Insert(ElementType X, List L, Position P); Position Header(List L); Position First(List L); Position Advance(Position P); ElementType Retrieve(Position P); void PrintList(const List L); void SwapWithNext(Position BeforeP, List L); void Qsort(List L, List tail);//快速排序核心算法 void QuickSort(List L);//快速排序驱动程序 #endif // !_List_H
fatal.h
#include<stdio.h> #include<stdlib.h> #define Error(Str) FatalError(Str) #define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1);
库函数QuickSort.c
// 引用头文件 #include "QuickSort.h" #include<stdlib.h> #include "fatal.h" //结构体定义 struct Node { ElementType Element; Position Next; }; //初始化链表 List MakeEmpty(List L) { if (L != NULL) DeleteList(L);//如果链表非空,则删除链表 L = malloc(sizeof(struct Node)); if (L == NULL) FatalError("Out of memory!"); L->Next = NULL; return L; } //删除链表 void DeleteList(List L) { Position P, Temp; P = L->Next; L->Next = NULL; while (P != NULL) { Temp = P->Next; free(P); P = Temp; } } //判断链表是否为空 bool IsEmpty(List L) { return L->Next == NULL; } //判断当前指针P是否指向链表最后一个元素 bool IsLast(Position P, List L) { return P->Next == NULL; } //插入元素X到位置P后面 void Insert(ElementType X, List L, Position P) { Position TmpCell; TmpCell = malloc(sizeof(struct Node)); if (TmpCell == NULL) FatalError("Out of Space!!!"); TmpCell->Element = X; TmpCell->Next = P->Next; P->Next = TmpCell; } //获取链表头 Position Header(List L) { return L; } //获取链表第一个元素的位置 Position First(List L) { return L->Next; } //获取位置P的下一个位置 Position Advance(Position P) { return P->Next; } //提取位置P处结构里面的值 ElementType Retrieve(Position P) { return P->Element; } //打印链表 void PrintList(const List L) { Position P = Header(L); if (IsEmpty(L)) printf("Empty list\n"); else { do { P = Advance(P); printf("%d ", Retrieve(P)); } while (!IsLast(P, L)); printf("\n"); } } //通过只调整指针来交换两个相邻的元素,BeforeP是要调换两个元素的前一 //个指针 void SwapWithNext(Position BeforeP, List L) { Position P, AfterP; if (BeforeP != NULL) { P = Advance(BeforeP); if (P != NULL) { AfterP = Advance(P); if (AfterP != NULL) { P->Next = AfterP->Next; BeforeP->Next = AfterP; AfterP->Next = P; } } } } //快速排序核心算法 void Qsort(List head, List tail) { //将链表分成2、4、8。。。,我们只说明开始分成2两条的情况 //将链表分成两条,小于枢纽元的链表1,大于等于枢纽元的链表2,链表1已经有了头结点head,链表2以枢纽元为头结点mid if (head->Next == tail || head->Next->Next == tail) return;//如果链表是空或者只有一个元素,则停止循环 List mid = head->Next;//指向枢纽元的指针 List p = head;//指向链表1,最后p指向链表1的尾元素 List q = mid;//指向链表2,最后q指向链表2的尾元素 ElementType pivot = mid->Element;//枢纽元 List t = mid->Next;//探测指针,指向下一个元素,查询是大于枢纽元还是小于枢纽元 while (t != tail)//当探测指针指向链表尾节点,循环结束 { if (t->Element < pivot)//当探测指针指向的元素<枢纽元,则把该元素接到链表1 p = p->Next = t; else q = q->Next = t;//当探测指针指向的元素>=枢纽元,则把该元素接到链表2 t = t->Next;//不管上一个元素大小如何,都要指向下一个元素 } //当循环完整个链表,然后将链表1和2拼接起来 p->Next = mid;//将小于枢纽元的链表1的尾节点指向枢纽元 q->Next = tail;//将链表2的尾节点指向tail Qsort(head, mid);//对链表1进行同样的循环,当满足113行条件,则停止这个递归 Qsort(mid, tail);//对链表2进行同样的循环,当满足113行条件,则停止这个递归 //当两个QuickSort都满足113行时,跳出递归循环,程序结束 } //快速排序驱动程序 void QuickSort(List L) { Qsort(L, NULL);//调用排序算法,第二个是NULL }
测试文件TestQuickSort
#include<stdio.h> #include "QuickSort.h" #include"fatal.h" #include<time.h> int main() { long amount; List L; Position P; L = MakeEmpty(NULL);//初始化链表 P = L; if (L == NULL) Error("Out of Space!!!"); printf("随机生成多少位数:"); scanf_s("%d", &amount); srand((unsigned)time(NULL)); for (long i = 0; i < amount; i++) { Insert(rand() % 1000000, L, P); P = Advance(P); } //printf("排序前的结果:"); //PrintList(L); QuickSort(L);//调用排序驱动程序 printf("排序后的结果:"); PrintList(L); }
运行结果如下图: