内部排序->交换排序->快速排序

文字描述 

  快速排序是对起泡排序的一种改进。它的基本思想是,通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

  一趟快速排序描述:假设待排序的序列为{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("\n关键字:");
 30     for(i=0; i<=L.length; i++){
 31         printf(" %-3d", L.r[i].key);
 32     }
 33     printf("\n其他值:");
 34     for(i=0; i<=L.length; i++){
 35         printf(" %-3c", L.r[i].otherinfo);
 36     }
 37     printf("\n\n");
 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\n",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作快速排序:\n\n");
 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("输入数据:\n");
113     PrintList(L);
114     //对顺序表L进行快速排序    
115     QuickSort(&L);
116 
117     return 0;
118 }
快速排序

 

运行

 

posted on 2018-07-25 18:36  LiveWithACat  阅读(271)  评论(0编辑  收藏  举报