几种快排方法比较
1、以nStart的值作为阈值划分,一次划分后小于nStart的值在左边,大于nStart的值在右边,然后递归此过程
void qsort1(long *sortArr, int nStart, int nEnd) { int m = 0; long t ; int r ; if(nStart >= nEnd) return ; t = sortArr[nStart] ; m = nStart ; for(r = nStart + 1; r <= nEnd; r++) { if(sortArr[r] < t) { long temp ; m++ ; temp = sortArr[r] ; sortArr[r] = sortArr[m] ; sortArr[m] = temp ; } } sortArr[nStart] = sortArr[m] ; sortArr[m] = t ; qsort1(sortArr, nStart, m - 1) ; qsort1(sortArr, m + 1, nEnd) ; }
2、从nStart作为比较的阈值,从nEnd开始比较,当发现有比nStart大的值的时候即将其挪到数列的后面,直到到达nStart的位置,这样可以省略上面的方法每次比较结束后的交换nStart的操作如下:
sortArr[nStart] = sortArr[m] ;
sortArr[m] = t ;
void qsort11(long *sortArr, int nStart, int nEnd) { int m ; long t ; int i ; long nTemp ; if(nStart >= nEnd) return ; m = nEnd + 1 ; i = nEnd + 1 ; t = sortArr[nStart] ; do { while(sortArr[--i] < t) ; nTemp = sortArr[--m] ; sortArr[m] = sortArr[i] ; sortArr[i] = nTemp ; }while(i != nStart) ; qsort11(sortArr, nStart, m - 1) ; qsort11(sortArr, m + 1, nEnd) ; }
3、以nStart作为比较的阈值,从数组首位两端进行比较,从左开始找到第一个大于等于nStart的值,从右开始找到第一个小于等于nStart的值,然后交换之,重复此过程直到遍历完整个数组,然后交换nStart的位置,这样小于等于nStart的都在其左边,大于等于的都在其右边,然后递归调用此过程
void qsort3(long *sortArr, int nStart, int nEnd) { int l ; int r ; long t ; long nTemp ; if(nStart >= nEnd) return ; t = sortArr[nStart] ; l = nStart ; r = nEnd + 1 ; for(; l < r; ) { do { l++ ; }while(l <= nEnd && sortArr[l] < t) ; do { r-- ; }while(sortArr[r] > t ) ; if(l > r) break ; nTemp = sortArr[l] ; sortArr[l] = sortArr[r] ; sortArr[r] = nTemp ; } sortArr[nStart] = sortArr[r] ; sortArr[r] = t ; qsort3(sortArr, nStart, r - 1) ; qsort3(sortArr, r + 1, nEnd) ; }
4、随即选取数组中的一个值作为阈值进行比较,其他同方法3
void qsort3r(long *sortArr, int nStart, int nEnd) { int l ; int r ; int k ; long t ; long nTemp ; int nRand ; double drate ; if(nStart >= nEnd) return ; nRand = rand() ; drate = nRand / RAND_MAX ; k = nStart + (int)((nEnd - nStart) * drate) ; t = sortArr[k] ; sortArr[k] = sortArr[nStart] ; sortArr[nStart] = t ; l = nStart ; r = nEnd + 1 ; for(; l < r; ) { do { l++ ; }while(l <= nEnd && sortArr[l] < t) ; do { r-- ; }while(sortArr[r] > t ) ; if(l > r) break ; nTemp = sortArr[l] ; sortArr[l] = sortArr[r] ; sortArr[r] = nTemp ; } sortArr[nStart] = sortArr[r] ; sortArr[r] = t ; qsort3r(sortArr, nStart, r - 1) ; qsort3r(sortArr, r + 1, nEnd) ; }
5、希尔排序
是一种增量递减(diminishing increment)排序,插入排序时希尔排序的一个特例,及增量为1,希尔排序根据增量选取的不同可得到很好的性能
void shellsortKn(long a[], int l, int r) { int i, h; for (h = 1; h <= (r-l)/9; h = 3*h+1) ; for ( ; h > 0; h /= 3) { for (i = l+h; i <= r; i++) { int j = i; long v = a[i]; while (j >= l+h && less(v, a[j-h])) { a[j] = a[j-h]; j -= h; } a[j] = v; } } }
对上述算法进行测试
#define maxN 10000000 typedef long itemType; #define randomLong rand() long doit(void (*sortprog)(), itemType a[], int l, int r) { long t ; t = GetTickCount() ; (*sortprog)(a, l, r) ; return (GetTickCount() - t) ; } int main() { itemType *a, *b; int N; int c1, c2, c3, c4, c5; srand( GetTickCount() ); a = malloc(maxN * sizeof(itemType)); b = malloc(maxN * sizeof(itemType)); printf(" N q1 q11 q3 q3r shs\n"); for (N = 12500; N <= maxN; N *= 2) { randArray(b, N); copyArray(a, b, N); c1 = doit(qsort1, a, 0, N-1); copyArray(a, b, N); c2 = doit(qsort11, a, 0, N-1); copyArray(a, b, N); c3 = doit(qsort3, a, 0, N-1); copyArray(a, b, N); c4 = doit(qsort3r, a, 0, N-1); copyArray(a, b, N); c5 = doit(shellsortKn, a, 0, N-1); printf("%7d %6d %6d %6d %6d %6d\n", N, c1, c2, c3, c4, c5); } free(a); free(b); scanf("%d", &N) ; return 0 ; }
我的机器配置如下:
intel core2 P7450
内存2G
windows 7 32bit
参考:
【1】 编程珠玑第二版 http://book.douban.com/subject/3227098/
【2】http://en.wikipedia.org/wiki/Shell_sort
【4】Shellsort