图解堆排序

2018 年 1 月 9 日 算法与数据结构 涛声依旧
来自:趣谈编程,作者: 涛声依旧


面试官:写一个堆排吧

我心想:幸好昨天刚看


堆排是基于堆的一种排序算法,对于堆的了解,请看可以管理时间的二叉堆(如果对堆的插入和删除不清楚,强烈建议先看堆),今天我们聊聊堆排的思想,复杂度以及稳定性


堆排思想

前情回顾:克给谦子解决了时间管理上的问题可以管理时间的二叉堆


过了几天后,谦子高兴地跑到老师跟前

老师,你的那个方法太好了,现在做事非常有次序

谦子

那就好,看来你已经理解了二叉堆了,今天你刚好来,顺便考考你

早知不来了,谦子心想

给你一个无序数组,你给把它排好序

谦子心想:上次去溪边游玩不是已经出过这个题吗,当时学会了冒泡排序,这次肯定不是那么简单,肯定和前几天的堆有关系

这个应该用到堆

谦子

恩恩,对,怎么用堆这个数据结构来排好一个数组中的元素呢?

如果将这个数组调整为小根堆,那么根据小根堆堆顶一直是最小元素的特性,我可以不断地取(删除)堆顶的元素,直到堆中只剩下一个元素,这样就可以得到一个递减的元素序列了

谦子

删除中交换操作会破坏堆有序

但下沉操作会重新调整堆

谦子画了一个图解释道


这样一直删除到只有一个元素的时候,整个数组就排好序了

谦子

删除包括三个步骤:               

① 交换堆顶与堆最后一个元素

       ② 堆大小(heapSize)减一               

  ③ 调整堆(sink(arr,1))               

        具体讲解请看:二叉堆                       

  

你刚才是建立在数组是小根堆的情况下进行的,那如何将无序数组调整成堆呢?

建堆

我可以遍历数组中的每个元素,给一个空堆不断插入元素,直到插完所有元素,这样就可以构造一个堆了

谦子

上浮(swim)操作会保持堆有序

这样一直把数组中的元素插完就建成一个小根堆了

谦子

恩恩,这确实是一种方法,但更常见的是用下沉(sink)操作自底向上构造一个堆

哦,这个怎么做?

谦子

初始的时候,无序数组逻辑上可以看成一颗完全二叉树

每个叶子节点可以视为一个大小为一的堆,我们可以自底向上从非叶子节点开始每层从右至左给每个节点都调用下沉(sink)方法,这样以当前节点为根节点的树就变为堆了

然后给左边的节点4执行下沉(sink)操作(同一层从右向左)

最后根节点执行下沉(sink)操作

这样整个完全二叉树就变成了一个最小堆

注意:在下沉(sink)某个节点的时候,这个节点的两个孩子必须是堆


堆排代码


太神奇了,还可以这样

谦子

恩恩,那你写一写建堆删除最小值的代码吧

克突然话锋一转

哦!好吧

谦子

又要写代码,谦子心想,虽说心中这样想,但还是要写的,思考了一会,只见谦子写下了如下代码

这里的 heapSize/2 就是第一个非叶子节点的下标

谦子

谦子解释道

过了一会谦子又写出了删除最小值的代码

恩恩,不错,那顺便写一下排序的代码吧

前两个都写出来了,剩下的排序就很简单了,按照之前的思路,先建立一个小根堆,然后不断地删除堆顶最小元素,删除N-1次就OK了

只需删除N-1次,剩下的那个自然是最大的,所以我循环N-1次

谦子

谦子解释道

恩恩,很好,这个排序就是今天要给你说的另一个排序:堆排序

谦子暗自惊叹老师的功力,不知不觉又学到了一个排序方法


时间复杂度


那你分析一下这个堆排序的时间复杂度吧

看到数学头疼的可以直接跳过看结论

谦子还没缓过神,又来了一个最让他头疼的时间复杂度

这个。。。,弟子不才,还请老师指点

谦子

这个排序时间复杂度稍微有点难,但只要你静下心来一步一步算,其实也不难

克拿出了笔和纸

你想一下堆排的整个过程,第一步建堆,第二步执行N-1次deleteMin()方法,最后取两者复杂度较高的就行了

建堆时间复杂度

建堆的时候时间消耗在下沉操作上,而下沉操作最多下沉到底,显然,高度为h的节点下沉代价为O(h)

堆中所有元素下沉代价之和就是建堆的代价(时间复杂度)

叶子节点高度为0,下沉代价为0

谦子目不转睛地

把堆中不同高度中的所有节点相加起来就是全部的节点

所以问题变为:

高度最高多高(高度上界)

高度h有多少节点

这里你记住两个结论

有兴趣的可以证证这两个结论

这里我们把不同高度的每个节点执行sink所需要的代价累加起来

好复杂啊,头都大了

谦子

如果感觉复杂,你最终记住建堆复杂度为O(n)就行了

谦子长舒一口气

N-1次删除复杂度

接下来就是N-1次的删除了

n-1次调用deleteMin

deleteMin中包含 swap操作和 sink操作

swap操作代价为常数,sink操作代价为lgn,swap操作相对于sink操作可以忽略不计

则相当于进行了n-1次sink操作

则一共花费的代价为:(n-1)*lgn ~ nlgn

故时间复杂度为O(nlgn)

两个步骤相加的复杂度为:O(n)+O(nlgn),O(nlgn)复杂度高于O(n),所以堆排序的时间复杂度为O(nlgn)

哦,这样啊,懂了

谦子


稳定性


那你说说堆排序是不是稳定的

不是稳定的,就拿5,7,13,5,这个序列来说吧,我用大根堆的结构排序,排序前后两个5的位置会发生变化

谦子

谦子说着说着画了一个图

初始状态的5的先后顺序和排完序的顺序明显不一样了(黄色5跑到红色5左边去了),所以这个排序不是稳定的

谦子

恩恩,不错,时间也不早了,早点回去休息吧

(完)


●本文编号555,以后想阅读这篇文章直接输入555即可

●输入m获取文章目录

推荐↓↓↓
 

Java编程

更多推荐18个技术类微信公众号

涵盖:程序人生、算法与数据结构、黑客技术与网络安全、大数据技术、前端开发、Java、Python、Web开发、安卓开发、iOS开发、C/C++、.NET、Linux、数据库、运维等。

登录查看更多
1

相关内容

排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序。若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程。
一份简明有趣的Python学习教程,42页pdf
专知会员服务
76+阅读 · 2020年6月22日
【经典书】Python计算机视觉编程,中文版,363页pdf
专知会员服务
139+阅读 · 2020年2月16日
【经典书】精通机器学习特征工程,中文版,178页pdf
专知会员服务
356+阅读 · 2020年2月15日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
一文读懂自注意力机制:8大步骤图解+代码
新智元
153+阅读 · 2019年11月26日
基于动画图解常用的机器学习算法
人工智能前沿讲习班
5+阅读 · 2018年12月26日
从示例中理解SVM算法(附代码)
论智
9+阅读 · 2018年5月10日
图解机器学习的常见算法
机器学习算法与Python学习
5+阅读 · 2018年4月2日
《算法(第4版)》导读(下)
图灵教育
7+阅读 · 2017年12月19日
图解机器学习
深度学习世界
3+阅读 · 2017年11月24日
图解高等数学|线性代数
遇见数学
39+阅读 · 2017年10月18日
BAT机器学习面试1000题系列(第76~80题)
七月在线实验室
5+阅读 · 2017年10月13日
BAT机器学习面试1000题系列(第46~50题)
七月在线实验室
7+阅读 · 2017年10月7日
Mesh R-CNN
Arxiv
4+阅读 · 2019年6月6日
Music Transformer
Arxiv
5+阅读 · 2018年12月12日
VIP会员
相关VIP内容
一份简明有趣的Python学习教程,42页pdf
专知会员服务
76+阅读 · 2020年6月22日
【经典书】Python计算机视觉编程,中文版,363页pdf
专知会员服务
139+阅读 · 2020年2月16日
【经典书】精通机器学习特征工程,中文版,178页pdf
专知会员服务
356+阅读 · 2020年2月15日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
相关资讯
一文读懂自注意力机制:8大步骤图解+代码
新智元
153+阅读 · 2019年11月26日
基于动画图解常用的机器学习算法
人工智能前沿讲习班
5+阅读 · 2018年12月26日
从示例中理解SVM算法(附代码)
论智
9+阅读 · 2018年5月10日
图解机器学习的常见算法
机器学习算法与Python学习
5+阅读 · 2018年4月2日
《算法(第4版)》导读(下)
图灵教育
7+阅读 · 2017年12月19日
图解机器学习
深度学习世界
3+阅读 · 2017年11月24日
图解高等数学|线性代数
遇见数学
39+阅读 · 2017年10月18日
BAT机器学习面试1000题系列(第76~80题)
七月在线实验室
5+阅读 · 2017年10月13日
BAT机器学习面试1000题系列(第46~50题)
七月在线实验室
7+阅读 · 2017年10月7日
Top
微信扫码咨询专知VIP会员