单链表形式实现排序算法。
这个快速排序主要利用递归调用。包含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);
}运行结果如下图:
