快速排序是用的最多的一种排序方法,《编程珠玑》在第十一章《排序》中讨论了快速排序的几个版本,其实版本的不同,都是体现在partition函数上。
partition版本1,其实就是《算法导论》给出的版本,很好理解;
int partition1(int a[], int begin, int end) { int pivotkey = a[end]; int i = begin; int j = begin - 1; int tmp; for (i = begin; i < end; i ++) { if (a[i] <= pivotkey) { j ++; tmp = a[j]; a[j] = a[i]; a[i] = tmp; } } j ++; tmp = a[j]; a[j] = a[end]; a[end] = tmp; return j; }
partition版本2:其实本科的时候最先学习快速排序,就是使用的这个版本。后来看到版本1,觉得版本1更好理解。但是该版本的效率更高,使用了两个指针:
int partition2(int a[],int begin, int end) { int pivotkey = a[begin]; int tmp; int low = begin; int high = end; while (low < high) { while (low < high && a[high] >= pivotkey ) --high; tmp = a[low]; a[low] = a[high]; a[high] = tmp; while(low < high && a[low] <= pivotkey) ++low; tmp = a[low]; a[low] = a[high]; a[high] = tmp; } return low; }
partition 版本3:对版本2的优化:其实不用每次交换a[low]和a[high],直接覆盖好了,类似于前面的插入排序的改进
int partition3(int a[],int begin, int end) { int pivotkey = a[begin]; int low = begin; int high = end; while (low < high) { while (low < high && a[high] >= pivotkey ) --high; a[low] = a[high]; while(low < high && a[low] <= pivotkey) ++low; a[high] = a[low]; } a[low] = pivotkey; return low; }
测试程序及其结果
# include <stdio.h> # include <stdlib.h> # include <time.h> # include "chapter11.h" # include "chapter12.h" # define N 500000 int cmp(const void* a,const void* b) { return *(int *)a - *(int *)(b); } int main() { // testchapter12 // int m = 10, n = 100; // genknuth(m, n); // genbyme(m,n); // int a[] = {5,7,6,4,2,8,6}; // int a[] = {6,4,10,12,7,8}; int a[N]; int i; for(i = 0; i < N; i ++) a[i] = rand()%(10 * N); int len = sizeof (a)/ sizeof(a[0]); clock_t start = clock(); // quickSort1(a, 0, len - 1); // quickSort2(a, 0, len - 1); // quickSort3(a, 0, len - 1); qsort(a,len,sizeof(a[0]),cmp); // partition3(a,0,len - 1); clock_t end = clock(); printf("the cost time is %ld", (long int)end - start); return 0; }
结果:
版本1:the cost time is 141
版本2:the cost time is 125
版本3:the cost time is 110
qsort: the cost time is 94