快速排序
来源:互联网 发布:php显示图片缩略图 编辑:程序博客网 时间:2024/06/05 10:59
摘要:快速排序是一个性能良好的排序算法,目前C++的STL中的sort()内部实现也是依靠快速排序,本文简要介绍快排和代码实现。
关键字:排序算法,快速排序,数据结构
- 步骤
- 优化
- 代码
前提说明:整数数组,目标是从左到右为依次递增
步骤
(1)选择一个最接近于整个数组平均数的数,作为pivot,放在数组的第low位置;
(2)从数组的尾部向首部开始搜索,比较,找出比pivot要小的数,放在数组的第low位置;
(3)从数组的首部向尾部开始搜索,比较,找出比pivot要大的数,放在数组的第high位置;
不断重复(2)和(3),知道low和high相遇就停止,此时,pivot处于整个数组比较中间的位置,而pivot位置的左边子数组中所有的数比pivot小,pivot位置的右边子数组中所有的数比pivot大,形成了一个初步有序的状态。然后左边数组和右边数组分别执行(1)(2)(3)的操作,直到整个数组基本有序。
优化
在这里,有4个地方是可以进行优化的。
第一,选择一个怎么样的pivot,这是很重要的,只有当pivot尽可能接近于整个数组的平均数时,效率是最高的。很多书上说是取数组的第一个元素,这是不严谨的。常用的方法有3数取中,即取首中尾3个元素的中间元素作为pivot。
第二,在(2)和(3)中交换元素时,也可以进行优化,这里说的优化主要是指pivot的移动。许多版本的代码中是使用swap(low,high),首先pivot取自于data[low],在尾部指针找到交换的数后,和pivot交换,此时pivot处于high指针这个位置,而下一步,首部指针找到可交换的数时,又把pivot交换到data[low]这里来,由此反反复复,pivot的位置经历了很多次不必要的赋值。因此,这里可以优化为,把交换变为赋值,当尾部指针找到满足条件的数时,直接把high位置的数赋值到low位置,即data[low]=data[high];而当首部指针找到可交换的数时,直接把low位置的数赋值到high位置,即data[high]=data[low];当low和hign相遇后,再把pivot赋值给data[low];
第三,优化小数组的排序。快速排序使用了递归,递归伴随着对栈的操作,这属于额外的性能开销。当数据量很大时,栈的操作相对来说占的比重就比较小,但是数据量不大 时,这个操作的性能消耗占的比重就不小了。因此可以尝试着,当数据量小时,使用直接插入排序,当数据量大时,使用快速排序。当然,这感觉不算是快速排序的范畴里了。
第四,第三点说到,快排使用了递归,也就使用了栈,而栈是属于处理器内部的存储空间,大小十分有限,而快排处理的数据量一般比较大,所以对栈空间大小是有严格要求的。假如出现极端情况,即pivot的划分很不合理,那么就有可能出现pivot两边的数组中,有一个数组的元素个数会接近于n,那么递归的深度也接近于n,这开销确实不容小觑。因此,可以实施尾递归优化。即先对[low,pivot]这部分数组进行递归排序,下一次排序low去pivot+1,然后再重新选取新的pivot,如此进行直到整个数组有序。这就极大的保证了递归的深度和占用栈的空间大小。
代码
#include<iostream>#define ARRAY_SIZE 10using namespace std;void swap(int &a, int &b){ int temp; temp = a; a = b; b = temp;}int partion(int v[], int low, int high){ // 关键字取左中右三数之中 int pivot, m; m = low + (high - low) / 2; if(v[low] > v[high]) swap(v[low], v[high]); if(v[m] > v[high]) swap(v[m], v[high]); if(v[m] > v[low]) swap(v[m], v[low]); pivot = v[low]; while(low < high) { while(low < high && v[high] >= pivot) high--; //swap(v[low], v[high]); v[low] = v[high]; while(low < high && v[low] <= pivot) low++; //swap(v[low], v[high]); v[high] = v[low]; } v[low] = pivot; return low;}void qsort(int v[], int low, int high){ int pivot; while(low < high) { pivot = partion(v, low, high); qsort(v, low, pivot - 1); low = pivot + 1; }}int main(void){ int v[ARRAY_SIZE] = { 7,1,5,6,8,4,2,3,9,0 }; qsort(v, 0, ARRAY_SIZE - 1); for(int i = 0; i < ARRAY_SIZE; i++) { cout << " " << v[i]; } return 0;}
参考资料:《大话数据结构》
- 快速排序
- 快速排序
- 快速排序
- 快速排序!
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 基于keras的二分类的网络训练代码
- java SHA1WithRSA 算法
- 动态规划:怪盗基德的滑翔翼
- 数据库开发规范
- unity遮挡剔除的开启
- 快速排序
- 微信公众号开发
- Android 多线程handler,runnable,asyctask使用
- strtok的实现——用于按给定符号分割字符串的函数
- 【OpenCV】大牛博客
- 二叉树的创建、先序、中序、后序、层序的递归与非递归算法(java)
- javaString常用方法
- java 网络爬虫之多线程抓取文件
- Android synchronized()同步线程