数字能排序字符串不能排序_动图解说堆排序原理,让体育生也能看得明白
本篇的主旨是理解二叉堆结构,所以具体实现代码会留到第二篇讲解。
提到堆,其实Java中的优先队列PriorityQueue就是基于堆结构实现的;
而Java中的延迟队列DelayQueue里面就用到了PriorityQueue;
再比如kafka中基于时间轮TimingWheel实现的延时定时器, 同样离不开DelayQueue的配合。
这一切都和堆息息相关。
1 数组和树
堆其实就是一个数组结构, 如图
下面我们来点小魔法, 把数组变成树!
这个数组对应的树结构就是下面这样:
数组结构的下标和树结构的节点对应关系如下:
如果根节点对应的数组下标是0, 那么对于 i 节点,
左右子节点的位置为 2i +1和 2i+2;
i 节点的父节点位置为 ( i-1)/2;
简单理解了数组和树之后,下面我们进入正题。
2 最小堆结构
首先我们来一个乱序的数组:
这个数组对应的树结构:
这只是一个简单的树结构, 还不是堆, 堆结构是下面这样子的:
这是一个最小堆, 可以看到根节点, 也就是堆顶, 是数组中最小的那个元素。
同时,整一个大的堆, 是由很多个小的堆组成的。
比如左边这个小堆, 也是符合最小堆的定义, 堆顶的4是三个数字中最小的:
右边的小堆也是一个最小堆, 堆顶的3是最小的数字:
那么怎么把一颗树变成一个最小二叉堆呢?
3 插入和上浮
最简单的办法, 就是新建一个空的堆(一个空的数组), 把乱序数组中的所有元素依次插入到堆中, 在这个过程中堆会通过上浮来调整自身的结构。
下面我们来解析下上面的动画:
首先, 是往堆中 插入 元素, 比如往下面的这个最小堆中插入数字1:
当1插入数组尾部之后, 就处于树的最后一个叶子节点的位置:
然后通过 上浮 操作, 把A移到合适的位置。
简单来说就是先和A的父节点比较, 如果比父节点小, 就和父节点交换位置, 这个过程一直持续到A的父节点比A小, 或者A已经到达堆顶的位置。
下面继续数字1这个例子, 当1插入数组尾部之后, 会和他的父节点8作比较:
1比父节点8小, 交换位置:
1再和他的父节点4作比较:
1比父节点4小, 交换位置后1到达堆顶, 形成了一个最小堆结构。
4 删除和下沉
接下来讲讲堆节点的删除, 这里的删除是指取出堆顶的节点。
我们把堆顶的元素取出后, 堆会把剩下的数字中最小的那个数字再次推到堆顶的位置。
仔细看动画,这里值得注意的是, 取出堆顶的元素, 并不是直接把堆顶的元素删除。什么意思呢?
在JavaScript中, 数组的pop操作就是把数组中最后一个元素删除; 而Java中的堆栈Stack也有pop操作, 同样是把最后一个元素移除。
而堆的 删除 操作, 也是基于pop操作来实现。这样做是为了维持完全二叉树的结构。
比如我们要把堆顶的1删除:
1. 先把根节点和最后一个节点交换位置, 也就是1和6交换位置;
此时堆顶不再是最小的数字,最小堆的特性被打破, 接下来我们要对堆顶的元素进行 下沉 操作, 把树结构重新调整为堆结构。
2. 先比较左右子节点大小,与最小节点交换位置 ;
3. 继续步骤2;
继续上面的例子,当1节点移除后,此时会先对堆顶6的左右子节点进行大小比较, 找出比较小的那个子节点,也就是右节点3:
然后, 节点6再和右节点3比较:
节点6下沉, 此时6已经是叶子节点了, 下沉操作结束, 可以看到此时整棵树已经重新变回了最小堆结构:
5 堆排序
有趣的是, 通过上面简单的【插入并上浮】 和 【删除并下沉】 , 我们就可以对乱序数组执行堆排序了。
下面对乱序数组进行堆排序:
堆化,插入并上浮:
删除并下沉:
排序完成后的数组:
最后对堆排序的总结就是:
1. 先把乱序数组堆化 (文中使用的是插入+上浮)
2. 再通过pop操作删除堆顶元素, 通过下沉调整堆结构
6 堆化 Heapify
平常的使用堆排序肯定不会再新建一个空的堆, 再把乱序数组的元素逐个插入堆中, 这样太浪费空间, 下一章我们来讲一下堆化。
7 色谱图
简单了解了堆排序后, 我们来看看16个元素进行堆排序后生成的色谱图
也有网友说这是大肠图, 感兴趣的可以看看这篇文章了解下【译】排序算法可视化之色谱图, 后面本公众号会开一个系列专门讲解这种有趣的静态可视化方法。
我们把这个图拆成两部分来看, 首先是左边部分
这就是堆排序的第一步, 堆乱序数组堆化的过程
再来看看右边部分
可以看到, 堆排序的第二步就是pop操作把堆顶元素移除, 图中也体现得非常清晰,先把堆顶元素移到尾部, 被移除的元素就相当于排好序了.
每次移除元素后, 都会对新的堆顶节点执行下沉操作, 也就是图中pop和pop之间的红框部分, 我们可以清晰地看到堆在自我调节的过程
排序结束之后, 由浅到深的颜色依次呈现在我们眼前!
温馨提示
文中的动画是基于d3.js制作而成。
作者:字节武装
链接:https://www.jianshu.com/p/d4cd1d54e5ef
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
数字能排序字符串不能排序_动图解说堆排序原理,让体育生也能看得明白相关推荐
- 数据结构排序算法实验报告_数据结构与算法-堆排序
堆排序 堆排序是指利用堆这种数据结构所设计的一种排序算法.堆是一个近似完全二叉树的结构,并同时满足堆的性质:即子节点的键值或索引总是小于(或者大于)它的父节点,堆排序的时间复杂度为O(nlogn).( ...
- python字符串连接数字电视_【学习猿地】初识python脚本 #千万别看,我怕你控制不住...
>编写python程序的文件,称为python的脚本或程序 >要求当前的python脚本的文件后缀名必须是.py #### pycharm使用注意 > 需要明确的知道你当前pycha ...
- 计算方位角_全站仪各方面应用的原理、操作及计算,看这篇就对了!
来源:豆丁施工 版权归原作者所有 全站仪是什么? 全站仪,即全站型电子速测仪.它是随着计算机和电子测距技术的发展,近代电子科技与光学经纬仪结合的新一代既能测角又能测距的仪器,它是在电子经纬仪的基础上增 ...
- 全站仪和手机连接软件_全站仪各方面应用的原理、操作及计算,看这篇就对了!...
来源:豆丁施工 版权归原作者所有 全站仪是什么? 全站仪,即全站型电子速测仪.它是随着计算机和电子测距技术的发展,近代电子科技与光学经纬仪结合的新一代既能测角又能测距的仪器,它是在电子经纬仪的基础上增 ...
- 全站仪和手机连接软件_全站仪各方面应用的原理、操作及计算,看这篇就对了...
全站仪是什么? 全站仪,即全站型电子速测仪.它是随着计算机和电子测距技术的发展,近代电子科技与光学经纬仪结合的新一代既能测角又能测距的仪器,它是在电子经纬仪的基础上增加了电子测距的功能,使得仪器不仅能 ...
- js 中 中文、空格、数字、字符串混合排序
最近有个需求,需要对后台的数组对象按照某个属性进行排序,属性值可能是 中文.字符串.数字.特殊字符.空字符串,网上大部分都只是针对某一个类型进行排序,在参考这篇博客的基础之上https://blog. ...
- 字母排序 字符串跟字符串比较大小 字符串跟数字比较大小
两个字符比较返回的都是Boolean值 对于非数字进行比较 则会先转换为数字进行比较 所有包含NaN的比较返回值都为false 包括NaN==NaN 特殊情况 当两边都是字符串 不会转换为数字进行比较 ...
- Java对字符串中数字进行按自然顺序排序
Java对字符串中数字进行按自然顺序排序 import java.util.Arrays;public class Test01 {public static void main(String[] a ...
- python字符串去重排序_python实现字符串转数字排序-女性时尚流行美容健康娱乐mv-ida网...
女性时尚流行美容健康娱乐mv-ida网 mvida时尚娱乐网 首页 美容 护肤 化妆技巧 发型 服饰 健康 情感 美体 美食 娱乐 明星八卦 首页 > 高级搜索 python 取子 字符 串 ...
最新文章
- java父子表_数据库二维表转父子关系,java,stream,list
- ajaxfileupload返回结果undefined_Null amp; Undefined 简易对比
- 【Fiddler学习】Fiddler抓包HTTPS请求和手机抓包
- 修改anaconda3 jupyter notebook 默认路径
- AI:《DEEP LEARNING’S DIMINISHING RETURNS—深度学习的收益递减》翻译与解读
- 从零开始入门 K8s| K8s 的应用编排与管理
- 文件服务器和客户模式有什么区别,客户端和服务器端编程有什么区别?
- 对一个“世纪数学难题”的重新思考
- 数据结构实验之栈二:一般算术表达式转换成后缀式
- linux删除目录tmpab是什么意思_linux 下tmp目录文件怎么被删除的?
- VScode配置C语言环境 亲测 可用!!!
- 从零基础入门Tensorflow2.0 ----八、42. 自定义流程
- .text urlRewrite介绍
- 基于android的订餐系统 答辩ppt,外卖订餐系统答辩PPT
- (java毕业设计)基于java汽车租赁管理系统源码
- 小程序云开发(二) 上传图片到云服务器、上传图片并展示
- Ffmpeg实例,为视频添加一个循环播放的背景音乐(混声)
- 2022年北京购房攻略二 (城区交通篇)
- nodejs+vue基于决策树算法的大学生就业预测系统
- android做一个音乐播放器,制作一个简单的Android版的音乐播放器