《C算法》笔记10:快速排序
2015-09-07 18:17
176 查看
快速排序于1960年由Hoare发明,公认为效率最高的排序算法之一,广泛应用于C++标准库中。快速排序是典型的分治算法,或者确切的说,是典型的先治后分(conquer-divide)算法:
quick_partition将a[r]元素置为标准位,比a[r]小的移到数组前端,比a[r]大的移到数组后端,最后返回a[r]在新数组中的位置。
1、当待排序数组有序时,快速排序性能将严重退化。退化表现在每次选取的a[r]永远最大,造成递归函数调用层数为N。同理,待排序数组反序时,快速排序时间复杂度退化到O(N2)O(N^2)。
因此,r直接决定了快速排序的性能。一般用随机选取或者三中值法来选取r。
2、由前文所述,插入排序在部分有序的数组中性能较好。当递归函数已经得到较小尺寸的数组时,可采用插入排序,以减少不必要的函数调用开销。
在本地VS2012环境下,(CPU:i5-3470)对一长度为5M的随机生成数组进行实验:
实验可见,当最小尺寸在20-50之间时,所优化结果为较佳。
3、快速排序是不稳定的。当希望使用稳定排序时,参见归并排序。
4、现代std库中的sort采用的技术更为复杂。当然,sort当中有其他开销,使得在本实验中表现并不良好。
#define LT(a, b) (a < b) #define EXCH(a, b) {int t = a; a = b; b = t;} #define CMXCH(a, b) if(LT(b, a)) EXCH(a, b)
void quick_sort(int *a, int l, int r) { if(r <= l) return; int i = quick_partition(a, l, r); //conquer quick_sort(a, l, i - 1); //divide quick_sort(a, i + 1, r); }
quick_partition将a[r]元素置为标准位,比a[r]小的移到数组前端,比a[r]大的移到数组后端,最后返回a[r]在新数组中的位置。
int quick_partition(int *a, int l, int r) { int i = l - 1, j = r; int v = a[r]; while(true) { while(v > a[++ i]); while(v < a[-- j]) if(i == j) break; if(i >= j) break; EXCH(a[i], a[j]); } EXCH(a[i], a[r]); return i; }
1、当待排序数组有序时,快速排序性能将严重退化。退化表现在每次选取的a[r]永远最大,造成递归函数调用层数为N。同理,待排序数组反序时,快速排序时间复杂度退化到O(N2)O(N^2)。
因此,r直接决定了快速排序的性能。一般用随机选取或者三中值法来选取r。
2、由前文所述,插入排序在部分有序的数组中性能较好。当递归函数已经得到较小尺寸的数组时,可采用插入排序,以减少不必要的函数调用开销。
void quick_sort_v3m(int *a, int l, int r, int d) // d为“较小的尺寸” { if(r - l <= d) { insert_sort2(a, l, r); return; } int m = (l + r) / 2; EXCH(a[m], a[r - 1]); CMXCH(a[r - 1], a[r]); CMXCH(a[l], a[r - 1]); CMXCH(a[r - 1], a[r]); int i = quick_partition(a, l + 1, r - 1); quick_sort_v3m(a, l, i - 1, d); quick_sort_v3m(a, i + 1, r, d); }
在本地VS2012环境下,(CPU:i5-3470)对一长度为5M的随机生成数组进行实验:
实验可见,当最小尺寸在20-50之间时,所优化结果为较佳。
3、快速排序是不稳定的。当希望使用稳定排序时,参见归并排序。
4、现代std库中的sort采用的技术更为复杂。当然,sort当中有其他开销,使得在本实验中表现并不良好。
相关文章推荐
- 黑马程序员——集合框架(双列集合:Map接口)
- 利用不相交集来生成迷宫(只有关键代码)
- AsyncTask类简单总结
- Android SDK开发包国内下载地址
- java基础—4.面向对象
- Android 之 下拉框(Spinner)的使用
- JAVA生成随机数
- table换行
- nginx安装出错
- android状态栏一体化(改变状态栏的背景颜色)开源工程推荐
- CoreMotion框架-iOS设备的核心运动
- linux常用命令
- git clone
- 纯css实现仿ios表单开关
- cocos2d-x 用cocos code IDE 打包android mac
- Java遍历时删除List、Set、Map中的元素(源码分析)
- JVM内存模型以及垃圾回收
- Java遍历时删除List、Set、Map中的元素(源码分析)
- adb code
- Aittit.attilax超级框架 api 规划大全