引用严蔚敏的《数据结构》的话,在所有数量级都为nlgn的排序方法中,快排的常数因子k最小。这意味着快排是目前被认为是最好的一种内部排序方法。

下面先放出快排的代码:

void QuickSort(int *a,int low,int high){if(low<high){int l = low,h = high,flag = a[low];while(l<h){while(l<h&&a[h]>=flag) h--;a[l] = a[h];while(l<h&&a[l]<=flag) l++;a[h] = a[l];}a[l] = flag;QuickSort(a,low,l-1);QuickSort(a,l+1,high);}}

所以分析快排的时间性能就很有必要了。影响快排的重要因素是枢轴数的选择。理想情况下,如果每次划分两个子数组的长度都相同,那么效率肯定会是最高的,那如果我们每次都找到数组中的中位数作为枢轴数那就可以了。然而输入的数组本身肯定是无序的,如果要找到中位数就需要有序输入,这个做法肯定不行的,我们对快排的改进必须建立在保证递归里的一次操作时间复杂度为O(n)。

教科书上给出的方法是选择数组第一个数为枢轴数。

优化一:随机选择枢轴数

当数组部分有序,选择第一个数为枢轴数,快排的比较次数会大幅度增加,而且划分子数组的长度会差异较大,当数组基本有序,快排就蜕变为冒泡了,如果随机选择枢轴数,就可以利用随机性来规避这种情况,下面我们来修改一下代码为:

//要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;void QuickSort_random(int *a,int low,int high){if(low<high){int random = ((rand()%(high-low+1))+low);int l = low,h = high,flag = a[random];swap(a[random],a[low]);while(l<h){while(l<h&&a[h]>=flag) h--;a[l] = a[h];while(l<h&&a[l]<=flag) l++;a[h] = a[l];}a[l] = flag;QuickSort_random(a,low,l-1);QuickSort_random(a,l+1,high);}}

改代码有一点需要注意的是,随机选取了一个数,要把这个数的位置放回第一位,然后其余代码跟原来一样就好了(其实我想不懂为什么不放回第一位,按照本来的代码就是错误的,不知道怎么修改才会不出错,希望有大神可以指导我),为了代码的正确性,不管选择哪个数为枢轴数,我都是将这个数放到第一位。

优化二:三者取中选择枢轴数

为了更容易模拟出找到整体数组的中位数,我们可以选取三个数(第一个,最后一个和中间的数),然后取三个数的中位数作为枢轴数,修改后的代码如下:

//取三者中其关键宇取中值的记录为枢轴void quick_sort_three(int *s, int l, int r) {//取随机数为枢纽if (l < r){int x = 0;int x1 = s[l], x2 = s[r], x3 = s[(l + r) >> 1];if (x1 <= x2&&x2 <= x3) {x = x2;swap(s[r], s[l]);}else if (x2 <= x1&&x1 <= x3) {x = x1;swap(s[l], s[l]);}else {x = x3;swap(s[(l+r)/2], s[l]);}int i = l, j = r;while (i < j){while (i < j && s[j] >= x) // 从右向左找第一个小于x的数 j--;if (i < j)s[i++] = s[j];while (i < j && s[i] <= x) // 从左向右找第一个大于等于x的数 i++;if (i < j)s[j--] = s[i];}s[i] = x;quick_sort_three(s, l, i - 1); // 递归调用  quick_sort_three(s, i + 1, r);}}

这时我们来测试一下性能。

(测试环境为vs2017,release,x86,硬件为surfacepro4,i5低压+8G+256G)

输入的数组为随机生成的int整数,共有100组,长度分别为1000,10000,50000,100000

 

选第一个数
100组的平均时间/ms

随机选一个数
100组的平均时间/ms

三者取中
100组的平均时间/ms

STL
sort

规模n

 

 

 

 

1000

0.03

0.09

0.06

0.03

10000

0.71

1.16

0.91

0.95

50000

4.68

5.58

4.14

4.45

100000

8.51

11.06

8.72

9.47

神奇的是,测试结果居然是完全没有优化过的快排最快!随机选择枢轴数的方法最慢!

对于随机选择的方法,我的猜想是可能rand()这个方法消耗的时间比较多所以会变慢,然后三者取中的方法接近STL的sort方法,应该是比较好的优化方法。至于普通的快排为什么会这么快我想不明白,但是必须尊重实验结果,所以打脸的数据我还是贴出来了,欢迎各位下载我的代码测试一下或者提出意见,最后附上测试的代码的github地址,谢谢!

https://github.com/810410738/sort_test/

快速排序的优化——枢轴数的选择相关推荐

  1. 内部排序(五)快速排序(上)- 概述与选择枢轴

    快速排序终于要来了,快速排序也是交换排序的一种,其实讲快速排序前应该先讲讲冒泡排序,因为快速排序是对冒泡排序的一种改进,那就先来用最快速度复习一下冒泡排序: 冒泡排序:假设要对待排序了做升序排序,那么 ...

  2. java版排序算法简介及冒泡排序以及优化,选择排序,直接插入排序,希尔排序,堆排序,快速排序及其优化前言 2 分类 2 稳定性 3 时间复杂度 4 Java实现版本 5 1、冒泡排序 6 2、选择排序

    好吧 ~~csdn太难用了....尼玛...写了半天的也无法弄进去...lz正在找更好地博客,or放在github上打算.. 下边是lz自己的有道云分享,大概内容是 http://note.youda ...

  3. 26.K-均值算法的优化目标、随机初始化、聚类数的选择

    一.K-均值算法的优化目标 K-均值最小化问题,是要最小化所有的数据点与其所关联的聚类中心点之间的距离之和 K-均值的代价函数(又称畸变函数 Distortion function)为: J(c(1) ...

  4. 快速排序深度优化详解

    正如它的名字所体现,快速排序是在实践中最快的已知排序算法,平均运行时间为O(NlogN),最坏的运行时间为O(N^2).算法的基本思想很简单,然而想要写出一个高效的快速排序算法并不是那么简单.基准的选 ...

  5. 快速排序及优化(Java实现)

    一. 普通快速排序 找一个基准值base,然后一趟排序后让base左边的数都小于base,base右边的数都大于等于base.再分为两个子数组的排序.如此递归下去. public class Quic ...

  6. UE4项目优化(帧数优化)相关知识

    控制台命令 r.screenpercentage 0~100 0是百分之百 如果改了这个 游戏运行超级流畅说明瓶颈在GPU上 stat fps 显示帧率(Frame Per Second)(或者快捷键 ...

  7. mysql stack is full_mysql优化之表的优化与列类型选择

    表的优化与列类型选择 列选取原则#### 1.字段类型优先级 整型 > date,time > char,varchar > blob 因为 整型,time运算快,节省空间,char ...

  8. seo优化时网站_选择关键词的方法

    网站优化中关键词的选择和布局很关键,直接影响网站的流量.选好关键词是第一步,接下来怎么布局也很重要,今天小编带大家分享一些技巧. 1.根据内容选择关键词 在选择关键词之前,我们应该首先确定网站的内容并 ...

  9. 【数字信号去噪】基于matlab粒子群算法优化VMD分解分量选择数字信号降噪【含Matlab源码 1979期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[数字信号去噪]基于matlab粒子群算法优化VMD分解分量选择数字信号降噪[含Matlab源码 1979期] 点击上面蓝色字体,直接付费 ...

最新文章

  1. Google Test(GTest)使用方法和源码解析——概况
  2. MySQL中字段约束有哪些_mysql字段约束
  3. java 组合框_Java知多少(88)列表和组合框
  4. 使用pytorch最关键的几个点
  5. C++内存管理与内存泄漏及其检测
  6. 对于知识的可连接性的理解
  7. 有源光缆AOC知识百科汇总
  8. [ASM]查看加密的vba代码
  9. JAVA:jar包下载地址大全
  10. VS2010启动总是遇到异常提示的解决
  11. 博客V7之后,喜庆排名进入2000之内
  12. 数独游戏——数模处理(MATLAB整数规划)
  13. Java程序员技术栈
  14. 青春不散场,CSDN毕业季有奖征文开启啦~~
  15. HTML-img图片详解
  16. 袁宝华 oracle,关键词优化难易分析_SEO优化难度分析 - 站长工具
  17. 精品咖啡知识不能不知道的8个地方
  18. c语言大作业俄罗斯方块,C语言自己写俄罗斯方块(完整版)
  19. 初学SQL 注入之常见的几种注入类型
  20. java 利用工具包Geotools实现不同坐标系之间坐标转换

热门文章

  1. 微信小程序存在的风险_微信小程序存在哪些风险
  2. 如何围绕某一轴(不是xyz)旋转——transform.RotateAround
  3. 网络空间安全竞赛D模块解析
  4. android 监听sim卡状态,android监控sim卡有没有服务示例(sim卡管理)
  5. 华为鸿蒙HarmonyOS,华为鸿蒙HarmonyOS 2.0
  6. 已知信码序列为1011_专升本计算机网络:校验码
  7. 数字重复次数统计软件
  8. 晨枫U盘维护V2.0_512M版给U盘分区
  9. PLASTIGAUGE塑料间隙规的正确使用步骤你知道多少?
  10. 计算机数据表格方框,WPS表格使用心得:不容小觑的小方框 -电脑资料