AI 助理
备案 控制台
开发者社区 开发与运维 文章 正文

看动画学算法之:排序-快速排序

简介: 看动画学算法之:排序-快速排序

目录


  • 简介
  • 快速排序的例子
  • 快速排序的java代码实现
  • 随机快速排序的java实现
  • 快速排序的时间复杂度


简介



快速排序也采用的是分而制之的思想。那么快速排序和归并排序的区别在什么地方呢?


归并排序是将所有的元素拆分成一个个排好序的数组,然后将这些数组再进行合并。


而快速排序虽然也是拆分,但是拆分之后的操作是从数组中选出一个中间节点,然后将数组分成两部分。


左边的部分小于中间节点,右边的部分大于中间节点。


然后再分别处理左边的数组合右边的数组。


快速排序的例子



假如我们有一个数组:29,10,14,37,20,25,44,15,怎么对它进行快速排序呢?


先看一个动画:


056298.gif


我们再分析一下快速排序的步骤。


我们选择的是最左边的元素29作为中间点元素,然后将数组分成三部分:[0, 14, 15, 20, 25],[29],[44, 37]。


中间节点29已经排好序了,不需要处理。


接下来我们再对左右分别进行快速排序。最后就得到了一个所有元素都排序的数组。


快速排序的java代码实现



我们先来看最核心的部分partition,如何将数组以中间节点为界,分成左右两部分呢?


我们的最终结果,是要将array分割成为三部分。


首先我们选择最左侧的元素作为中间节点的值。然后遍历数组中的其他元素。


假如m=middleIndex,k=要遍历的元素index


考虑两种情况,第一种情况是数组中的元素比中间节点的值要大。


image.png


这种情况下,m不需要移动,k+1继续遍历即可。


第二种情况下,数组中的元素比中间节点的值要小。


image.png


因为m左边的元素都要比中间节点的值要小,所以这种情况下m需要+1,即右移一位。


现在m+1位置的元素要么还没有进行比较,要么就是比中间节点的值要大,我们可以巧妙的将m+1位置的元素和k位置的元素互换位置,这样仍然能够保证m左侧的元素要比中间节点的值要小。


将上面的分析总结成java代码如下:


private int partition(int[] array, int i, int j) {
        //选择最左侧的元素作为中心点,middleValue就是中心点的值
        int middleValue = array[i];
        int middleIndex = i;
        //从i+1遍历整个数组
        for (int k = i+1; k <= j; k++) {
            //如果数组元素小于middleValue,表示middleIndex需要右移一位
            //右移之后,我们需要将小于middleValue的array[k]移动到middleIndex的左边,
            // 最简单的办法就是交换k和middleIndex的值
            if (array[k] < middleValue) {
                middleIndex++;
                //交换数组的两个元素
                swap(array, k , middleIndex);
            } //如果数组元素大于等于middleValue,则继续向后遍历,middleIndex值不变
        }
        // 最后将中心点放入middleIndex位置
        swap(array, i, middleIndex);
        return middleIndex;
    }


最后我们需要将最左侧的元素和中间节点应该在的index的元素互换下位置,这样就将中间节点移动到了中间位置,并返回中间位置。


再来看下divide的代码:


public void doQuickSort(int[] array, int low, int high) {
        //递归的结束条件
        if (low < high) {
            //找出中心节点的值
            int middleIndex = partition(array, low, high);
            //数组分成了三部分:
            // a[low..high] ~> a[low..m–1], pivot, a[m+1..high]
            //递归遍历左侧部分
            doQuickSort(array, low, middleIndex-1);
            // a[m] 是中心节点,已经排好序了,不需要继续遍历
            //递归遍历右侧部分
            doQuickSort(array, middleIndex+1, high);
            log.info("QuickSort之后的数组:{}",array);
        }
    }


divide的代码就很简单了,找到中间节点的位置之后,我们再分别遍历数组的左右两边即可。最后得到排好序的数组。


随机快速排序的java实现



上面的例子中,我们的中间节点的选择是数组的最左元素,为了保证排序的效率,我们可以从数组中随机选择一个元素来作为中间节点。


private int partition(int[] array, int i, int j) {
        //随机选择一个元素作为中心点,middleValue就是中心点的值
        int randomIndex=i+new Random().nextInt(j-i);
        log.info("randomIndex:{}",randomIndex);
        //首先将randomIndex的值和i互换位置,就可以复用QuickSort的逻辑
        swap(array, i , randomIndex);
        int middleValue = array[i];
        int middleIndex = i;
        //从i遍历整个数组
        for (int k = i+1; k <= j; k++) {
            //如果数组元素小于middleValue,表示middleIndex需要右移一位
            //右移之后,我们需要将小于middleValue的array[k]移动到middleIndex的左边,
            // 最简单的办法就是交换k和middleIndex的值
            if (array[k] < middleValue) {
                middleIndex++;
                //交换数组的两个元素
                swap(array, k , middleIndex);
            } //如果数组元素大于等于middleValue,则继续向后遍历,middleIndex值不变
        }
        // 最后将中心点放入middleIndex位置
        swap(array, i, middleIndex);
        return middleIndex;
    }


上面的代码,我们在分区的时候,先选择出一个随机的节点,然后将这个随机的节点和最左侧的元素交换位置,后面的代码就可以重用上面的QuickSort的代码逻辑了。


快速排序的时间复杂度



从上面的分析我们可以看出,每次分区的时间复杂度应该是O(N),而divide又近似二分法,所以总的时间复杂度是O(N logN)。

flydean程序那些事
目录
相关文章
睡觉待开机
|
1月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
睡觉待开机
46 0
b3c447iaqrtq2
|
1月前
|
搜索推荐 算法 Java
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
b3c447iaqrtq2
17 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
软件求生
|
1月前
|
算法 搜索推荐 Java
算法实战:手写归并排序,让复杂排序变简单!
归并排序是一种基于“分治法”的经典算法,通过递归分割和合并数组,实现O(n log n)的高效排序。本文将通过Java手写代码,详细讲解归并排序的原理及实现,帮助你快速掌握这一实用算法。
软件求生
37 0
东方睿赢
|
1月前
|
算法 关系型数据库 MySQL
揭秘MySQL中的版本号排序:这个超级算法将颠覆你的排序世界!
【8月更文挑战第8天】在软件开发与数据管理中,正确排序版本号对软件更新及数据分析至关重要。因MySQL默认按字符串排序版本号,可能出现&#39;1.20.0&#39;在&#39;1.10.0&#39;之前的不合理情况。解决办法是将版本号各部分转换为整数后排序。例如,使用`SUBSTRING_INDEX`和`CAST`函数从`software`表的`version`字段提取并转换版本号,再按这些整数排序。这种方法可确保版本号按逻辑正确排序,适用于&#39;major.minor.patch&#39;格式的版本号。对于更复杂格式,需调整处理逻辑。掌握此技巧可有效应对版本号排序需求。
东方睿赢
86 3
热爱技术的小郑
|
1月前
|
算法 搜索推荐
算法设计 (分治法应用实验报告)基于分治法的合并排序、快速排序、最近对问题
这篇文章是关于分治法应用的实验报告,详细介绍了如何利用分治法实现合并排序和快速排序算法,并探讨了使用分治法解决二维平面上的最近对问题的方法,包括伪代码、源代码实现及时间效率分析,并附有运行结果和小结。
热爱技术的小郑
12 0
yinying293
|
1月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
yinying293
18 0
龙大吉
|
2月前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
【7月更文挑战第12天】归并排序是高效稳定的排序算法,采用分治策略。Python 实现包括递归地分割数组及合并已排序部分。示例代码展示了如何将 `[12, 11, 13, 5, 6]` 分割并归并成有序数组 `[5, 6, 11, 12, 13]`。虽然 $O(n log n)$ 时间复杂度优秀,但需额外空间,适合大规模数据排序。对于小规模数据,可考虑其他算法。**
龙大吉
65 4
众所周知
|
2月前
|
算法 搜索推荐 编译器
算法高手养成记:Python快速排序的深度优化与实战案例分析
【7月更文挑战第11天】快速排序是编程基础,以O(n log n)时间复杂度和原址排序著称。其核心是“分而治之”,通过选择基准元素分割数组并递归排序两部分。优化包括:选择中位数作基准、尾递归优化、小数组用简单排序。以下是一个考虑优化的Python实现片段,展示了随机基准选择。通过实践和优化,能提升算法技能。**
众所周知
48 3
百锦再@新空间代码工作室
|
2月前
|
算法 搜索推荐 C#
算法——快速排序
算法——快速排序
百锦再@新空间代码工作室
21 0
weixin_836869520
|
3月前
|
算法 Java 调度
Java数据结构与算法:拓扑排序
Java数据结构与算法:拓扑排序
weixin_836869520
35 0

热门文章

最新文章

  • 1
    深度 | 大数据算法应用的测试发展之路
  • 2
    RTC场景中的几个关键算法
  • 3
    《推荐系统:技术、评估及高效算法》一3.1 简介
  • 4
    某研究院的二叉树深度优先遍历变种的算法面试题以及答案
  • 5
    预约直播 | 流批一体机器学习算法平台Alink介绍及应用
  • 6
    算法学习之路|人口普查
  • 7
    机器学习算法:补一个k-近邻算法的测试
  • 8
    《数字视频和高清:算法和接口》一1.11幅型比的比较
  • 9
    【机器学习算法-python实现】svm支持向量机(1)—理论知识介绍
  • 10
    数据结构与算法(三) 线性表之双向链表
  • 1
    m基于LDPC编译码的matlab误码率仿真,对比SP,MS,NMS以及OMS四种译码算法
    211
  • 2
    【AI 初识】描述遗传算法概念
    138
  • 3
    【AI 初识】人工智能中使用了哪些不同的搜索算法?
    272
  • 4
    机器学习算法原理与应用:深入探索与实战
    88
  • 5
    【C言专栏】递归算法在 C 语言中的应用
    57
  • 6
    基于DCT变换的彩色图像双重水印嵌入和提取算法matlab仿真
    72
  • 7
    排序算法--------计数排序
    33
  • 8
    Matlab决策树、模糊C-均值聚类算法分析高校教师职称学历评分可视化
    49
  • 9
    【Python机器学习专栏】异常检测算法在Python中的实践
    157
  • 10
    圆填充( CIRCLE PACKING)算法圆堆图圆形空间填充算法可视化
    81
  • 相关课程

    更多
  • 智能运维赛(复赛):利用数据和算法,快速定位系统异常并进行根因分析
  • 智能创作赛(复赛):相册应用中的视频故事生成算法介绍
  • 智能创作赛(初赛):相册应用中的故事生成算法介绍
  • 相册服务中的故事生成算法介绍
  • Go语言核心编程 - 数据结构和算法
  • 神经网络概览及算法详解
  • 相关电子书

    更多
  • 数据+算法定义新世界
  • 袋鼠云基于实时计算的反黄牛算法
  • Alink:基于Apache Flink的算法平台
  • 相关实验场景

    更多
  • 推荐系统入门之使用ALS算法实现打分预测
  • 欧拉图的构造性证明与算法实现
  • RSA密码算法设计与实现
  • RSA非对称加密算法
  • 使用Swing算法实现商品推荐
  • 下一篇
    通义千问API入门教程

    玻璃钢生产厂家淮安玻璃钢动漫卡通雕塑设计校园玻璃钢仿铜雕塑玻璃钢火车头雕塑湘阴玻璃钢花盆花器丹阳玻璃钢雕塑厂家电话女装商场柱子美陈图片沈阳商场美陈制作街区商场美陈安徽蘑菇玻璃钢雕塑夜叉雕塑图片玻璃钢佛像重庆市玻璃钢雕塑找哪家河源革命主题玻璃钢雕塑贵州欧式玻璃钢雕塑制作周口大象玻璃钢雕塑九江特色玻璃钢雕塑定做价格德州玻璃钢卡通雕塑报价博物馆玻璃钢雕塑水母绍兴玻璃钢花盆开发济南玻璃钢雕塑定制工厂芜湖人物玻璃钢雕塑定做郑州玻璃钢现代雕塑北京玻璃钢玻璃钢雕塑公司玻璃钢卡通大门雕塑昆山百货商场美陈南京玻璃钢雕塑加工厂家玻璃钢雕塑报价怎么报辽宁玻璃钢雕塑供应商浙江开业商场美陈怎么样济南动物玻璃钢雕塑销售厂家安康玻璃钢人物雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

    玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化