文字描述
快速排序是对起泡排序的一种改进。它的基本思想是,通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
一趟快速排序描述:假设待排序的序列为{L.r[s], L.r[s+1], … , L.r[t]},首先任意选取一个记录(通常选第一个记录L.r[s])作为枢轴(pivot), 然后按下述原则重新排列其余记录:将所有关键字较它小的记录都安置在它的位置之前,将所有关键字较它大的记录都安置在它的位置之后。由此以该“枢轴”记录最后所落得位置i作分界线,将序列{L.r[s], L.r[s+1], … , L.r[t]}分割成两个子序列{L.r[s], L.r[s+1], …, L.r[i-1]}和{L.r[i+1], L.r[i+2], …, L.r[t]}。至此,完成一趟快速排序。
示意图
算法分析
快速排序的平均时间为knlnn, 其中n为记录个数,k为某个常数。经验证明,在所有同数量级(nlogn)的排序方法中,其平均时间性能最好。但是,若初始记录序列按关键字有序或基本有序时,快速排序将蜕化为起泡排序,其时间复杂度为n*n.
辅助空间为1,但是需要一个栈空间来实现递归。若每趟排序都将记录序列均匀的分割成长度相接近的两个子序列,则栈的最大深度为[log2n]+1;若每趟排序之后,枢轴位置都在最边上,则栈的最大深度为n。
是不稳定的排序方法
代码实现
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define DEBUG 5 6 #define EQ(a, b) ((a) == (b)) 7 #define LT(a, b) ((a) < (b)) 8 #define LQ(a, b) ((a) <= (b)) 9 10 #define MAXSIZE 20 11 typedef int KeyType; 12 typedef char InfoType; 13 typedef struct{ 14 KeyType key; 15 InfoType otherinfo; 16 }RedType; 17 18 typedef struct{ 19 RedType r[MAXSIZE+1]; 20 int length; 21 }SqList; 22 23 void PrintList(SqList L){ 24 int i = 0; 25 printf("下标值:"); 26 for(i=0; i<=L.length; i++){ 27 printf("[%d] ", i); 28 } 29 printf(" 关键字:"); 30 for(i=0; i<=L.length; i++){ 31 printf(" %-3d", L.r[i].key); 32 } 33 printf(" 其他值:"); 34 for(i=0; i<=L.length; i++){ 35 printf(" %-3c", L.r[i].otherinfo); 36 } 37 printf(" "); 38 return ; 39 } 40 41 /* 42 *交换顺序表L中子表L.r[low,...,high]的纪录,枢轴记录到位, 43 *并返回其所在位置,此时在它之前(后)均不大于(小于)它 44 */ 45 int Partition(SqList *L, int low, int high) 46 { 47 //用字表的第一个记录作枢轴纪录 48 L->r[0] = L->r[low]; 49 //pivotkey表示枢轴记录的关键字值 50 KeyType pivotkey = L->r[low].key; 51 52 //从表的两端交替向中间扫描 53 while(low<high){ 54 //将比枢轴记录小的记录移到低端 55 while(low<high && L->r[high].key>=pivotkey) --high; 56 L->r[low] = L->r[high]; 57 58 //将比枢轴记录大的记录移到高端 59 while(low<high && L->r[low].key<=pivotkey) ++low; 60 L->r[high] = L->r[low]; 61 } 62 //枢轴记录到位 63 L->r[low] = L->r[0]; 64 //返回枢轴位置 65 return low; 66 } 67 68 /* 69 * 对顺序表L中子表L.r[low,...,high]作快速排序 70 */ 71 void QSort(SqList *L, int low, int high) 72 { 73 74 KeyType pivotkey; 75 if(low<high){ 76 //将L.r[low,...,high]一分为二,低(高)于pivotkey的均不大于(小于)它 77 pivotkey = Partition(L, low, high); 78 #ifdef DEBUG 79 printf("一趟快速排序后(low=%d, high=%d), pivotkey=%d ",low, high, pivotkey); 80 PrintList(*L); 81 #endif 82 //对低字表递归排序,pivotkey是轴枢位置 83 QSort(L, low, pivotkey-1); 84 //对高子表递归排序 85 QSort(L, pivotkey+1, high); 86 } 87 } 88 89 /*对顺序表L作快速排序*/ 90 void QuickSort(SqList *L) 91 { 92 printf("对顺序表L作快速排序: "); 93 QSort(L, 1, L->length); 94 } 95 96 int main(int argc, char *argv[]) 97 { 98 if(argc < 2){ 99 return -1; 100 } 101 SqList L; 102 int i = 0; 103 for(i=1; i<argc; i++){ 104 if(i>MAXSIZE) 105 break; 106 L.r[i].key = atoi(argv[i]); 107 L.r[i].otherinfo = 'a'+i-1; 108 } 109 L.length = (i-1); 110 L.r[0].key = 0; 111 L.r[0].otherinfo = '0'; 112 printf("输入数据: "); 113 PrintList(L); 114 //对顺序表L进行快速排序 115 QuickSort(&L); 116 117 return 0; 118 }
运行