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

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

这个快速排序主要利用递归调用。包含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 QuickSort(List head, List tail);//快速排序核心算法
20 #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 QuickSort(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     QuickSort(head, mid);//对链表1进行同样的循环
155     QuickSort(mid, tail);//对链表2进行同样的循环
156 }

测试文件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, NULL);//调用排序函数排序
23     printf("排序后的结果:");
24     PrintList(L);
25 }

时间: 2024-12-24 00:46:53

排序算法----快速排序(链表形式)的相关文章

排序算法----快速排序java

快速排序是对冒泡排序的一种改进,平均时间复杂度是O(nlogn) import java.util.Arrays; import java.util.Scanner; public class test02{ public static void main(String[] args) { int n = 1; while (n != 0){ Scanner scanner = new Scanner(System.in); n = scanner.nextInt(); int s[] = ne

经典排序算法 - 快速排序Quick sort

经典排序算法 - 快速排序Quick sort 原理,通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列 举个例子 如无序数组[6 2 4 1 5 9] a),先把第一项[6]取出来, 用[6]依次与其余项进行比较, 如果比[6]小就放[6]前边,2 4 1 5都比[6]小,所以全部放到[6]前边 如果比[6]大就放[6]后边,9比[6]大,放到[6

排序算法--快速排序

快速排序之所以特别快,主要是由于非常精炼和高度优化的内部循环. 像归并排序一样,快速排序也是一种分治的递归算法.数组S排序的基本算法由下列简单的四部组成: 1.如果S中元素个数是0或1,则返回 2.取S中任一元素v,称之为pivot(枢纽元,主元,基准) 3.将S-{v}分成两个不想交的集合:S1={x∈S-{v} | x <= v} 和 S2={x∈S-{v} | x > v} 4.返回{QuickSort(S1)后,继随v,继而QuickSort(S2) 为了完成上述的步骤3,有两种常用方

java八种排序算法---快速排序

快速排序基本思想:挖坑填数+递归分治 快速排序使用分治法的策略,把一个串行分成2个子串行,快速排序又是一种分而治之的思想在排序算法是上的典型应用,本质上看,快速排序应该算冒泡排序基础上的递归分治法,快速排序名字简单粗暴,顾名思义就是快而且效率高,它是处理大数据最快的算法之一了. 算法描述:1.从数列中任意挑出一个数作为基准(pivot) 2.重新排序,所有比基准大的数放在基准左边,所有比基准大的数放在基准右边,这样排序一遍后该基准就位于数列的中间,这个就被称为分区操作(partition) 3.

排序算法----快速排序(数组形式)

这个快速排序主要利用递归调用,数组存储方式.包含3个文件,头文件QuickSort.h,库函数QuickSort.c,测试文件TestQuickSort. 其中Cutoff可以自己给定,这个当开始给定的数组(或者递归调用产生的子数组)的元素个数<=20个时,采用插入排序.一般认为当元素个数<=20时,插入排序更快.这个20不是固定的,在这附近浮动都可以的. 头文件QuickSort.h 1 #ifndef QuickSort_H 2 #define QuickSort_H 3 #define

白话排序算法--快速排序

前言: 写到快速排序时,之前已经进行了冒泡.选择.插入排序,发现算法问题很多东西都是和实际问题相逆的,实际你可能会由外及里,由上及下,可是算法里面它有时就需要你由里往外去扩散,好比最里面的是小成果,然后一次次往外变化,成果也慢慢变大,最后直至达到最终成果为止.本篇快速排序方法因为调用了递归,你就可以逆着由里及外来思考问题. 写这篇文章光画图就花费了我2小时时间,越抽象就越不好形容和比喻,画的不好,希望各位不要吐槽. 快速排序:先快速排序将队列一分为二,然后对每个队列进行递归调用快速排序方法,直至

排序算法--快速排序算法解析

一.快速排序算法思路 ①.取待排序列表的第一个元素p,通过归位算法,挪移他到列表中正确的位置. ②.列表被元素p分成两部分,左边都比元素p小,右边都比元素p大. ③.通过递归,在两部分,重复1.2步骤,直至列表有序. 归位算法动画演示: 二.快速排序算法代码示例 1 def partition(l,left,right):#归位算法 2 temp = l[left] #保存归位元素 3 while left <right: 4 while l[right]>=temp and left<

经典排序算法--快速排序

一.快速排序的基本思想: 快速排序使用了分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小.之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的. 二.快速排序的三个步骤 1) 选择基准:在待排序列中,按照某种方式挑出一个元素,作为 "基准"(pivot): 2) 分割操作:以该基准在序列中的实际位置,把序列分成两个子序列.如果为升序,则此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大:而基准则在排序后正确的位置上.

经典排序算法——快速排序

对于一个int数组,请编写一个快速排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2,2,3,3,5] class QuickSort { public: int* quickSort(int* A, int n) { // write code here if(A==NULL || n<2) return A; process(A,0,n-1); return A; } int* process(int*