当前位置: 首页 > ai >正文

【Java】Arrays.sort:DualPivotQuicksort

一,概述

本文,笔者欲探索JDK内部排序算法实现,并记录心得。本文只解读DualPivotQuicksort,对于TimSort不在本文讨论范文。

其一,Arrrays.sort内部对于int[]、float[]、long[]、double[]等基本数组,使用的快排是双轴快排,它相对于普通快排,优化了最差的时间复杂度,毕竟在快排中,如果哨兵选择不当,时间复杂度会瞬间退回O(N^2)。

其二,Arrays内部对小数组排序优化,使用了插入排序,在小数组中更高效。

其三,Arrays支持ForkJoinTask多线程排序,使用parallelSort即可,并且给出了parallelSort高效临界阈值,低于此阈值不会开启多线程。

二,实现

以sort为入口,

内部调用DualPivotQuicksort,字义上即双哨兵快速排序

接下来,便是该算法实现了,

1,如果使用了parallelSort,且当size > MIN_PARALLEL_SORT_SIZE (4 << 10),即2^12时,才会开启parallelism,否则效率会低于单线程排序。

2,调用sort方法,传入a、low、high,

跟进sort

传入bits = 0,暂且忽略mixedInsertSort和tryMergeRuns。

以上便是对小数组的排序优化,当size<MAX_INSERTION_SORT_SIZE(44)时,插入排序更加高效,

随后,便进入双轴快排两个哨兵的选取算法

1,选取step,是数组长度的八分之三 + 3,即 step = length&

2,从数组中取5个点,作为e1,e2,e3,e4,e5,

e3是整个数组中间值,e1,e5根据step选点,e2是e1和e3中间值,e4是e3和e5中间值,

e2大致在 ((3/8*size+3) + size / 2)/2位置,不赘述

3,根据e1,e2,e4,e5值,两两大小比较,交换值,最后满足e1<=e2<=e4<=e5

紧接着,e3也参与比较,最后满足e1<=e2<=e3<=e4<=e5

1,高位低位保留

2,当满足e1<e2<e3<e4<e5,即5个哨兵,值均不同时,则进入双轴快排算法分支,

3,两个哨兵取e1和e5,即选取5个点最小值与最大值,

1,将数组首位值赋值到e1,e5位置

2,从index1开始,找到第一个大于pivot1的下标,并记录为lower;

从index size-2开始,找到第一个小于pivot2的下标,并记录upper;

如此操作后,便划分了三个区域,如注释,

low~lower:值全部小于pivot1;

upder~end:值全部大于pivot2;

然后,使用第三个指针k,对lower~upper中间值进行扫描并交互,要求k~upper值满足

pivot1<=&&<=pivot2,直至k与lower重合,

再将哨兵返回到lower,upper位置,

如此以来,便得到一个新的序列,满足如下条件

e1,e5即选取的哨兵,e1<e5,lower\upper即哨兵点,

接下来,便是对low~lower,lower~upper,upper~end进行递归排序

以上即是对lower~upper,upper~end进行递归排序,而low~lower仍在本函数栈中继续进行,即将lower赋值给high(end = high - 1),别忘了,这个sort可是死循环函数。

这样,便能对三个区段再次递归排序,

如果无法满足e1<e2<e3<e4<e5,则进入单轴快排

单轴快排就不赘述了,此处,lower~upper == pivot

OK,关于Arrays.sort就讲到这里,下面顺带讲下多线程的sort算法,

三,ParallelSort

此算法是归并排序的多线程实现,根据depth判断是否使用sort函数,即不可分治区间时。

核心实现类是Sorter,间接集成ForkJoinTask,

compute中,当deptch > 0 时仍调用sort,对分治区域进行排序

depth来源以下算法

简单说,当排序序列size只有满足size>2^12,即分治终点是size < 2^12,便不再fork出更多的sorter了

onComplete中,便是归并,即Merger任务,同样也是继承ForkJoinTask,不赘述

http://www.xdnf.cn/news/13221.html

相关文章:

  • Spring AI MCP
  • AISHELL-5 全球首套智能驾舱中文语音交互数据集开源
  • 探秘鸿蒙 HarmonyOS NEXT:鸿蒙定时器,简单倒计时的场景应用
  • HAProxy 高可用部署方案详解
  • Blogx项目配置文件读取流程详解
  • echarts开发 | 数据可视化 -- 第一篇 echart配置项学习
  • 第13篇:数据库中间件缓存策略设计与热点数据优化实践
  • 华为云AI开发平台ModelArts
  • [小白]java之复杂JSON解析【超详细】
  • React19源码系列之合成事件机制
  • ARM内存理解(一)
  • Vim 高亮命令完整学习笔记
  • 实战案例-FPGA如何实现JESD204B确定性延迟
  • AIX智能下载器,轻松获取软件图标
  • 制作一款打飞机游戏69:编辑器升级
  • git常用操作3 替换仓库和分支管理
  • 3D图像渲染和threejs交互坐标系入门知识整理
  • Vim 列操作命令完整学习笔记
  • 力扣热题100之二叉树的层序遍历
  • 云原生核心技术 (2/12): Docker 入门指南——什么是容器?为什么它比虚拟机更香?
  • 大语言模型如何处理长文本?常用文本分割技术详解
  • PostgreSQL 的扩展pg_surgery
  • 基于区块链的供应链溯源系统:构建与实践
  • Git将本地文件推送到GitHub仓库
  • 51单片机读取PCF8563时钟芯片
  • 2025 高考:AI 都在哪些地方发挥了作用
  • 行为设计模式之Memento(备忘录)
  • 守护数字世界:网络安全核心技术与实践策略
  • VSCODE配置ESP-IDF芯片选择遇见的问题
  • 赛尔发布SHARE 5系列航测相机,外业更高效,建模更优质