快速排序的三路划分法
来源:互联网 发布: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
- 快速排序的三路划分法
- 排序算法之三路划分的快速排序
- 算法<基于三路划分的快速排序>
- <算法>基于三路划分的链表快速排序
- 三种快速排序算法的实现(递归算法、非递归算法、三路划分快速排序)
- 三种快速排序算法的实现(递归算法、非递归算法、三路划分快速排序)
- 三种快速排序算法的实现(递归算法、非递归算法、三路划分快速排序)
- 快速排序里面数组划分的三种方法
- 高级排序-快速排序-利用三数据取中划分的快速排序算法
- 快速排序(三路划分)解决大量重复元素
- 快速排序及优化(三路划分等)
- 算法--Java代码实现快速排序以及三路划分
- 微软面试题:三路划分快速排序---针对重复关键字的改进
- 快速排序(2)算法改进--小的子文件、三者取中、重复关键字三路划分
- 双向划分的快速排序
- 快速排序的Hoare划分
- 快速排序的三者取中划分
- 快速排序的最早划分方法:Hoare划分
- 【HDU】2817-A sequence of numbers(快速幂)
- Android中Toast的几种用法
- 能完全通过声音控制的,除了你家楼道里的灯泡,原来还有这么多产品
- Java做服务器开发语言
- ftrace 简介
- 快速排序的三路划分法
- 架构设计之如何写架构设计说明书
- Android Studio 导入OSChina客户端
- 64位win7旗舰版安装Microsoft Office Visio时报错
- SurfaceView的烦恼(一)-双缓存与清屏
- Binary Tree Level Order Traversal
- muduo for v210
- CDH 54Kkerberos impala start wrongly
- 空心三角形