快速排序的三路划分法

来源:互联网 发布:mac php环境配置 编辑:程序博客网 时间:2024/05/22 01:38
快速排序中带有大量重复关键字的时候,简单的由一个划分元素将元素分成两个子文件的算法效率低。很自然地想到了“荷兰国旗问题”,采用三路划分,将与划分元素相等的元素又区分出来,减少不必要的递归程序。
在快速排序中,当两个运动的指针遇到与划分元素相等的元素时候,将该元素数组的两端:左指针遇到的交换到数组的左端,右指针遇到的交换到数组的右端。需要增加两个指针,指向数组左右端可以存储相等元素的位置。

找到划分元素的位置之后,将相等元素由左右两端交换到划分元素的两边。

void quicksort_triple(Item a[], int l, int r){int i, j, k, p, q;Item v;if(r<=l) return;v = a[r];i = l-1;j = r;p = l-1;q = r;for(;;){while(less(a[++i], v));while(less(v, a[--j])){if(j==l) break;//跳出while循环}if(i>=j) break;//跳出for循环exch(a[i], a[j]);if(eq(a[i], v)){p++;exch(a[p], a[i]);}if(eq(v, a[j])){q--;exch(a[q], a[j]);}}exch(a[i], a[r]);//将左右两端与划分元素相等的元素交换到划分元素的两边i = i-1;j = i+1;for(k=l; k<=p; k++, i--){exch(a[k], a[i]);}for(k=r-1; k>=q; k--, j++){exch(a[k], a[j]);}quicksort_triple(a, l, i);quicksort_triple(a, j, r);}
综合三种快速排序的改进方法,实现快速排序如下

void quicksort_smallFile_median_triple(Item a[], int l, int r){int i, j, k, p, q;Item v;i = l-1;j = r;p = l-1;q = r;if(r-l <= M) {insertSort(a, l, r);return;//递归返回条件}exch(a[(l+r)/2], a[r-1]);//数组中间值与a[r-1]交换//三交换法对三个元素进行排序compexch(a[l], a[r-1]);compexch(a[l], a[r]);compexch(a[r-1], a[r]);v = a[r];for(;;){while (less(a[++i], v));while (less(v, a[--j])){if (j==l){break;}}if (i>=j){break;}exch(a[i], a[j]);if (eq(a[i], v)){p++;exch(a[p], a[i]);}if (eq(a[j], v)){q--;exch(a[q], a[j]);}}exch(a[i], a[r]);i = i-1;j = i+1;for (k=l; k<=p; k++, i--){exch(a[k], a[i]);}for (k=r-1; k>=q; k--, j++){exch(a[k], a[j]);}quicksort_smallFile_median_triple(a, l, i);quicksort_smallFile_median_triple(a, j, r);}
完整的测试程序

#include <stdio.h>#include <stdlib.h>typedef int Item;#define key(A) (A)#define less(A, B) (key(A)<key(B))#define exch(A, B) {Item t = A; A = B; B = t;}#define compexch(A, B) if(less(B, A)) exch(A, B)//最后A<B#define eq(A, B) (!less(A, B) && !less(B, A))#define M 10//M取值在5~20之间void insertSort(Item a[], int l, int r){int i, j;for (i = l+1; i <= r; i++){for(j = i; j > l; j--)compexch(a[j-1], a[j]);}}void quicksort_smallFile_median_triple(Item a[], int l, int r){int i, j, k, p, q;Item v;i = l-1;j = r;p = l-1;q = r;if(r-l <= M) {insertSort(a, l, r);return;//递归返回条件}exch(a[(l+r)/2], a[r-1]);//数组中间值与a[r-1]交换//三交换法对三个元素进行排序compexch(a[l], a[r-1]);compexch(a[l], a[r]);compexch(a[r-1], a[r]);v = a[r];for(;;){while (less(a[++i], v));while (less(v, a[--j])){if (j==l){break;}}if (i>=j){break;}exch(a[i], a[j]);if (eq(a[i], v)){p++;exch(a[p], a[i]);}if (eq(a[j], v)){q--;exch(a[q], a[j]);}}exch(a[i], a[r]);i = i-1;j = i+1;for (k=l; k<=p; k++, i--){exch(a[k], a[i]);}for (k=r-1; k>=q; k--, j++){exch(a[k], a[j]);}quicksort_smallFile_median_triple(a, l, i);quicksort_smallFile_median_triple(a, j, r);}int main(void){int i, N, sw;N = 10;sw = 0;int *a = (int *)malloc(N*sizeof(int));//为数据a分配相应的存储空间if (sw){for(i=0; i<N; i++){a[i] = 1000 * (1.0 * rand()/RAND_MAX);}}else{for (i = 0; i < N; i++){scanf("%d", &a[i]);}}puts("排序前");for(i=0; i<N; i++){printf("%d ", a[i]);}quicksort_smallFile_median_triple(a, 0, N-1);puts("\n排序后");for(i=0; i<N; i++){printf("%d ", a[i]);}printf("\n");system("pause");return 0;}

0 0
原创粉丝点击