引言

在快速排序分析中我们探讨了经典快排的实现,且进行了一些小优化。

但是若序列中包含大量重复的元素,这种情况下,快排的性能就不那么理想了。

下面开始学习三路快排的思想吧。

思路

将数组分为三部分,分别对应于小于、等于和大于哨兵元素v的子序列。

切分方法为从左到右遍历(扫描)数组一次,维护一个指针lt使得a[left..lt-1]中的元素都小于v,一个指针gt使得
a[gt+1..right]中的元素都大于v,一个指针i使得a[lt..i-1]中的元素都等于v,而a[i..gt]中的元素是还未扫描的。

一开始令i = left + 1,对a[i]v进行比较,根据比较情况作出不同的处理:

  • a[i]小于v,将a[lt]a[i]交换,将lti加1;
  • a[i]大于v,将a[gt]a[i]交换,将gt减1;
  • a[i]等于v,将i加1

以上操作会不断缩小gt - i的值,直到i > gt扫描结束。这时就成了上图切分后的情况。


假定元素数据如上图。


先让这三个指针就位。我们选取的哨兵元素v为6。


a[i]=3小于6,交换a[lt]a[i]:6和3,lti指针后移。

a[i]=8大于6,交换a[gt]a[i]:7和8,gt指针前移。


a[i]=7大于6,交换a[gt]a[i]:1和7,gt指针前移。


a[i]=1小于6,交换a[lt]a[i]:6和1,lti指针后移。


a[i]=2小于6,交换a[lt]a[i]:6和2,lti指针后移。


a[i]=1小于6,交换a[lt]a[i]:6和1,lti指针后移。


a[i]=6等于6,i指针后移。直到a[i]=5,交换6和5,lti指针后移。


i继续后移,然后不满足i <= gt的条件啦,跳出循环~

数组就被分为三部分,分别对应于小于、等于和大约哨兵元素v的子序列。

一次切分就完毕了,接下来只要对小于和大于v的部分进行同样的切分即可。

代码

private static <E extends Comparable<? super E>> void quick3Way(E[] a) {shuffle(a);quick3Way(a, 0, a.length - 1);
}/*** @param a* @param left* @param right* @param <E>*/
private static <E extends Comparable<? super E>> void quick3Way(E[] a, int left, int right) {if (right <= left) {return;}int lt = left, i = left + 1, gt = right;E v = a[left];//当 i > gt时跳出循环while (i <= gt) {int cmp = a[i].compareTo(v);//这里有个坑,注意和普通快排算法不一样,a[left]的元素是会发生变化的,因此需要用临时变量v缓存起来if (cmp < 0) {//a[i]小于v,将a[lt]和a[i]交换,将lt和i加1;swap(a, lt++, i++);} else if (cmp > 0) {//a[i]大于v,将a[gt]和a[i]交换,将gt减1;swap(a, gt--, i);} else {//a[i]等于v,将i加1i++;}}quick3Way(a, left, lt - 1);quick3Way(a, gt + 1, right);
}

排序算法之——三路快排分析相关推荐

  1. 经典排序算法 - 冒泡和快排总结

    排序有很多种方法,但人们首先总会想起冒泡和快排,现在总结一下这两种经典算法. 1. 冒泡 public void bubbleSort(int[] a){ for (int i = 0; i < ...

  2. 三路快排算法加强版(三路快排的再次改进)

    :不要忘记初心哈 :) 理论依据 快排算法的缺陷及其逐一改进 三路快排尽可能三等份划分区间 通过待排元素的区间长度划分? 通过待排元素的最值之差划分? 直接使用待排元素的最大值划分? 实验数据 大范围 ...

  3. LeetCode--75.颜色分类(三路快排,计数排序)

    颜色分类(C) 1. 题目描述 2. 题目解析 3. C语言实现 3.1 三路快排法 3.2 计数排序法 1. 题目描述 难度:中等 2. 题目解析 这道题需要注意一下几点: 原地进行排序,不可以另外 ...

  4. LeetCode 75. Sort Colors (python一次遍历,模拟三路快排)

    LeetCode 75. Sort Colors (python一次遍历,模拟三路快排) 题目分析: 本题需要实现数字只包含0,1,2的排序,并且要求一次遍历. 由于只用把数字隔离开,很容易想到快排的 ...

  5. 快速排序—三路快排 vs 双基准

    快速排序被公认为是本世纪最重要的算法之一,这已经不是什么新闻了.对很多语言来说是实际系统排序,包括在Java中的Arrays.sort. 那么快速排序有什么新进展呢? 好吧,就像我刚才提到的那样(Ja ...

  6. 209-希尔排序算法的思想和性能分析

    1.希尔排序算法的思想和性能分析 希尔排序可以认为是插入排序的一个优化,升级. 如果数据序列从大的方向,从全局看,已经是趋于有序的,那么插入排序是所有排序算法中效率最高的. 希尔排序就是从插入排序的这 ...

  7. 归并排序、快速排序、二路快排、三路快排python实现

    源代码: https://github.com/lzneu/Algrithm_python O(n*logn)级别的排序: |-归并排序     分成log(n)个层级 每个层级进行O(n)排序   ...

  8. 快速排序 详解(快速排序 双路快排 三路快排)

    注:内容,图片来自于慕课网liuyubobobo老师的课程.  官方代码链接:https://github.com/liuyubobobo/Play-with-Algorithms 快速排序 快速排序 ...

  9. java三路快排,java二路快排很慢

    老师,以下是我二路快排的java代码 public class quickSortTwoway { public quickSortTwoway() {}; public static void qu ...

  10. 数据结构之排序【归并排序和快排的顶级优化和快排的三种原理的实现及分析】 内含动态演示图

    文章目录 引言: 1.归并排序(MergeSort) 2.快速排序的优化(顶级优化) 3.快速排序的三种思路的代码实现及分析 4.归并排序和快排第3原理的测试 引言: 刚刚去回顾了一下递归实现的几个小 ...

最新文章

  1. 创建可微物理引擎Nimble,开源SOTA人体骨骼模型,斯坦福腿疾博士生用AI「助跑」人生...
  2. Qt Creator和VS2010中添加槽信号_差异与详解
  3. ITK:在图像上叠加标签图
  4. 小猪佩奇python_一段代码画出小猪佩奇社会人 Python
  5. 关于某些 Visual Studio Code 扩展程序无法在浏览器中运行的原因
  6. “只有DBA才能导入由其他DBA导出的文件”各种解决办法
  7. 打印ASCII码(信息学奥赛一本通-T1020)
  8. 虚拟化五、KVM虚拟化技术2
  9. centos 关机命令_Linux anacron命令用法详解
  10. 数据库 webSQL使用方法
  11. SAP ABAP 查询接口参数数据结构的报表
  12. php ssl证书安装,PHPWAMP如何开启SSL,Apache下如何安装ssl证书?配置ssl证书很简单...
  13. TEXMACS在ubuntu下的使用
  14. 电音制作收割者宿主软件-Cockos REAPER v6.15 x86 x64 WiN
  15. 软件测试思想者 - 初识抑郁症
  16. Java后端开发需要掌握什么
  17. Basic grammar of Python day2
  18. u盘中毒数据怎么才能恢复
  19. 我把3个镜头手机拍的照片发微信群,哥们说,现在手机摄像头越来越多,我有一个扫码就够了...
  20. SpringBoot集成Liquibase

热门文章

  1. aspnet ajax 1.0中的according控件
  2. 【win10.win7】在win10系统里面安装win7系统(亲测有效,方便快捷,无需自己设置开机启动项)
  3. 【react】XXX项目创建这个过程
  4. influxdb 配置
  5. RouteOS 频繁自启
  6. LeetCode--191--位1的个数
  7. Metasploit应用举例
  8. ATS连接 https
  9. 使用 Capistrano 和写作 Ruby 迭代边缘部署
  10. hdu 1671 Phone List (字典树)