快速排序是另一个分而治之排序算法。归并排序的重点在于合并,快速排序的重点在于分。(红色为每一次选取的候选轴点)

对于一个数组,起始为lo,结束为hi,轴点为pivot。通过每次选取不同的轴点,将轴点移动至某一位置,使得满足下述条件。

那么如何分呢?重点在于寻找轴点轴点需要满足的条件:其左侧元素都比其小,右侧元素都要比其大。如下图:

那么,快速排序就是使得所有元素逐个转换为轴点pivot,那么如何找到/构造这个轴点呢?

构造轴点

  1. 任取一个数组元素设置为候选轴点pivot,那就随意点---选择a[0]
  2. 中段U初始化为全集;比轴点小者归为前缀L,U左边界收缩;比轴点大者归为后缀G,U右边界收缩。

通过上面这个实例先来了解主要过程,再看代码估计就好一些了。

  1. 首先,lo=0,hi=9,右侧选取a[0]=6为候选轴点,a[0]挖掉,作为前缀L的起始位置(因为a[0]作为轴点已经保存,则a[0]可以作为坑,待填)。默认选取第一个为候选轴点,默认从右侧a[hi-1]开始进行逐个检查。
  2. a[hi=9]=7>轴点(6),归为后缀G,hi--;a[hi=8]=1<轴点(6),归为前缀L,lo++,a[8]连根拔起填入坑a[0],a[8]变为坑。
  3. a[lo=1]=3<轴点(6),归为前缀L,lo++;a[lo=2]=8>轴点(6),归为后缀G,hi--,a[2]连根拔起填入坑a[8],a[2]变为坑。
  4. ......依次根据上述规则,直至lo=hi时,轴点正式归位

则可以归纳为:左右边界lo、hi交替向内收敛,逐个检查元素,与轴点比较,小的归为前缀,大的归为后缀,lo=hi时,即为轴点归位点!!!

综上,mid=6,a[6]=pivot=6;分的过程如图。详细代码如下。

void quickSort(int a[], int low, int high)
{if (low < high) {int m = partition(a, low, high); // O(N)// a[low..high] ~> a[low..m–1], pivot, a[m+1..high]quickSort(a, low, m-1); // 递归地将左子阵列排序// a[m] = pivot 在分区后就被排序好了quickSort(a, m+1, high); // 然后将右子阵列排序}
}
int partition(int a[], int lo, int hi)
{int pivot = a[lo]; //选取侯取轴点 while(lo<hi)//从两点交替地向中间扫描,彼此靠拢 {while((lo<hi)&&(pivot<a[hi])) hi--;//向左扩展G if(lo<hi)a[lo++]= a[hi];//比轴点小的,都归入L while((lo<hi)&&(a[lo]<pivot))  lo++;//向右扩展L if(lo<hi)a[hi--]= a[lo];//比轴点大的,都归入G }a[lo]= pivot;//候选轴点,归位,返回其秩!!! return lo;
} 

对于上述算法

最好的情况:每次划分接近平均(L、G都接近n/2),轴点总是接近中央(hi-lo)/2,此时达到O(logn)

最坏的情况:每次划分都不均衡(比如轴点总是最大/最小元素),此时达到O(n^2),与冒泡排序相当。

做出下列改进,根据L、G、U三者大小关系的不变性,将数组分为四个部分:

轴点最初还是选取a[0],L左界是lo,L右界是mi,G左界是mi+1,G左界是mi,G右界是k,U左界是k,U右界是hi。

对于元素x逐个与轴点比较,若小于归为L,若大于归为G。当G区间足够大时,平滑式移动会比较复杂,在此采用滚动式移动比较简便,只要将x与G[mi+1]进行交换。为何能交换呢?因为G中元素均比x大,L中元素均比x小,这一条件始终满足。

遍历完成时,区间U会根据与轴点的大小,分别归入L、G,U会被完全分解,最终消失。最后一步,候选轴点与L右界进行交换,候选轴点归位,名副其实。

如上,可以归纳为:

上述是第一次遍历的最终结果,其余情况类似。

int partition(int a[], int lo, int hi)
{swap(a[lo],a[lo+rand()%(hi-lo+1)]);//随机交换,避免最坏情况的发生 int pivot = a[lo];int mi=lo;for(int i=lo+1;i<=hi;i++)//自左向右考察每个a[i] if(a[i]<pivot)//若[k]小于轴点,则将其 swap(a[++mi],a[i]);//与[mi]交换,L向右扩展 swap(a[lo],a[mi]);//候选节点归位(名副其实) return mi;//返回轴点的秩
}
void quickSort(int a[], int low, int high)
{if (low < high) {int m = partition(a, low, high); // O(N)// a[low..high] ~> a[low..m–1], pivot, a[m+1..high]quickSort(a, low, m-1); // 递归地将左子阵列排序// a[m] = pivot 在分区后就被排序好了quickSort(a, m+1, high); // 然后将右子阵列排序}
}

快速排序+改进版(邓俊辉老师讲授)相关推荐

  1. 数据结构 笔记--向量 C++ 语言版 邓俊辉老师

    邓俊辉老师的书. 1 有数组为什么还需要向量? 几乎所有程序设计语言中都会有数组,程序设计语言的开发者将数组作为一种内置的数据类型. 数组在刚开始初始化的时候就已经固定了长度,也可以依照下标查找,但还 ...

  2. 邓俊辉老师数据结构课程笔记

    文章目录 一.绪论 二.向量(查找和排序) 2.1知识点 2.2课后习题 三.列表 3.2 课后习题 四.栈与队列 五.二叉树 六.图 七.二叉搜索树 八.高级搜索树 一.绪论 1.复杂度分析的主要方 ...

  3. 计算几何(二) by邓俊辉老师

    凸包算法 最简 nlogn 极点算法n4-极边算法n3-incremental javis march / gift wrapping or 类似于 turning pattern insertion ...

  4. 邓俊辉老师的学堂在线数据结构课程中的迷宫

    不知道为啥我输出后的结果总是不对,迷宫的格子和上面的数字序号对不上,使用其他博主的也是一样不行,我自己改了一些东西的输出格式,输出后结果看着还行 下面代码是displayLaby.h这个文件 #pra ...

  5. 邓俊辉数据结构学习-3-栈

    栈的学习 栈的应用场合 逆序输出 输出次序与处理过程颠倒,递归深度和输出长度不易预知 不是很理解 实例:进制转换 大致思路:对于进制转换,我们一般使用的都是长除法,因此要保存每次得到的余数,但是最后算 ...

  6. 邓俊辉数据结构学习心得系列——数据结构中所研究的算法

    写在前面的话: 本文只是个人学习邓俊辉老师C++数据结构的整理,包含了很多个人的见解(从内容到材料的组织形式).所整理的内容不保证逻辑性和完整性,仅供参考. 算法的基本性质: 有正确的输入 有正确的输 ...

  7. 邓俊辉 《数据结构》笔记1 绪论

    邓俊辉 <数据结构>笔记1 绪论 CSDN转图床总是崩,如果全写完再上传一次要调好多,感觉很麻烦,所以写一点更新一点,会持续更新 提前发出来还有个好处就是push自己更新不会咕咕咕,哈哈 ...

  8. 邓俊辉算法训练营第三期(带完整课件)

    课程章节 第0周:调整姿势,迎接算法挑战 ୧(๑•̀◡•́๑)૭ 必读:课前预习清单 邓俊辉:学习算法的一些建议 专题课:扬帆起航,开启算法之旅 解题指南:如何提交作业&栈排序习题解答 习题课 ...

  9. 数据结构(邓俊辉)-[第8章]

    邓俊辉,清华大学计算机系副教授.1993.1995和1997年分别于清华大学计算机系获学士.硕士和博士学位,1997年起在清华大学任教,主要讲授"数据结构"和"计算几何& ...

最新文章

  1. java宠物医院_java宠物医院管理系统
  2. ACL 2021 | SimCLS: 概念简单但足够有效的对比学习摘要生成框架
  3. mybatis crud_MyBatis教程– CRUD操作和映射关系–第2部分
  4. javaweb(二十一)——JavaWeb的两种开发模式
  5. MATLAB 优化程序【profile简明用法】
  6. oracle 自定义类型使用方法,oracle pl/sql中使用自定义数据类型
  7. 解决 Linux 下 Sublime Text 中文输入
  8. 配置交换空间与文件系统的备份
  9. 用开源组件jcaptcha做jsp彩色验证码
  10. 合成未来宝宝照片_父母照片重叠是宝宝长相?关晓彤鹿晗颜值逆天,邓超孙俪……...
  11. 专治数仓疑难杂症!美团点评 Flink 实时数仓应用经验分享
  12. 16进制转浮点型_浮点型变量和BigDecimal的使用
  13. SVPWM分析、各个扇区详细计算以及Matlab仿真
  14. 面试题笔试-带答案-1
  15. 如何 ping ip 加 端口
  16. 为什么FUP PT5M 台式低速离心机深受大家喜爱
  17. 什么是“懒加载”(Lazy Loading)?
  18. batchsize和数据量设置比例_设置BatchSize
  19. 解决mac 10.11 以后 无法使用未签名第三驱动
  20. GAN(生成对抗网络) 解释

热门文章

  1. matlab全安装多大_从零开始安装Windows和Ubuntu双系统
  2. Ryuk紧盯“有缝的蛋”,利用学生盗版软件发起攻击
  3. 使用libexif开源库修改jpeg相片exif信息
  4. Java Swing面板布局之箱式布局BoxLayout
  5. Cubase 5.1.2 WiN 中文精简版音乐制作软件
  6. 计算机病毒和显示器,计算机病毒的监测、清除与身份认证
  7. 苹果备份备忘录android,iphone备忘录如何导出到另一个安卓手机?
  8. wpa_supplicant.conf文件详解
  9. 给Double赋值为0.0时,数据库中存储为null
  10. BGP路由之BGP选路规则