简易学算法之堆排序

Posted 硬件工程师的自我修养

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简易学算法之堆排序相关的知识,希望对你有一定的参考价值。



(请戳:  


因为昨天所介绍过选择排序,而堆排序是属于选择排序的一种,且效率更加高效,是普通选择排序的“升级版”!


相信有了昨天的简单选择排序的铺垫,堆排序估计不难!


可是等到要写才发现,如果要通过代码来讲解,那确实有些困难,而且我也还没有完全地理解代码方面的解析,就不好写出来了。


诚然,我目标是以个人理解到什么程度,然后写出来,大家看完之后,也能够达到我这个理解效果,我是一个老实的人!



“我用完之后是这个样子,而你们用完之后也会是这个样子!”

   ——国际知名影视巨星 成龙




难点关键在于这个“堆”字。


因为介绍“堆”需要用到有关“二叉树”的知识来解释...但用一篇文章来解释就有些不适合。我想,一篇文章只需要介绍一个知识点就够了,我是一个专一的人!


其实一般人也不需要怎么用到树的啦,又不是人人需要写程序,了解一下算法的思想就够了(没错,“二叉树”打算是作为与本篇 “堆排序”的接下来姐妹篇)


总之,先用图片介绍一下,同样是先有一个感性的认识吧。因为我是从这些图片理解了“堆排序”是怎么工作的。


来人,上图片!

遇到问题

有以下数列

91, 60, 96, 13, 35, 65, 46, 65, 10, 30, 20, 31, 77, 81, 22

请由小到大排列


堆排序

待排列的数列


先把这一排的数列,转换成堆。下图这个叫做 大顶堆


简易学算法之堆排序

之所以称为“大”,是因为每一个节点(父节点)都比下面的分支(子节点)的数字要大。


如: 父节点 96,比其子节点 65和91大;父节点65,比其子节点60和35大。


相反地,我们也会有小顶堆,那是用来从大到小排列时用的。



堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右子结点的值,称为小顶堆。




接下来开始排列,动起来,动起来:


简易学算法之堆排序


好了,大概有点感性理解了没?我又专门地画一些简单的图呢!


进入最大堆;我可以看到最大堆里顶点肯定是数列中最大的一个,96。


简易学算法之堆排序

把顶点96和最底层最右边的子节点22交换。


(这里注意一下,堆只是说明父节点比子节点要大,至于两个子节点之间的大小、子节点与其他层级的节点大小无关,因此堆初始最右边放的并不是最小的值,如图是 22,并不是最小值)


简易学算法之堆排序



简易学算法之堆排序

由于有空位,两个子节点 65 和 91 对比,91大,所以91成为父节点,顶上去!


简易学算法之堆排序


由于91移动上去,其下面的子节点要补充空位,同样把大的子节点移动上去。


简易学算法之堆排序


最后,22归位,补充空缺,这样就完成了一趟排序!堆也成为一个新的堆。

简易学算法之堆排序


红色的数96,表示已经排列完成的数了,不再参与排序。它是属于“有序排列”,而白色的数是叫做“无序排列”。


那什么是有序排列、无序排列呢?在上一篇: 


里介绍选择排序有这么一出:

简易学算法之堆排序


其中,大括号{ }外面的数,就是“有序排列”,括号里面的数就是“无序排列”。(这么说来,难怪这么奇葩的堆排序也称为是属于选择排序的一种了。)


上面的第一趟完成后,我们再重复开始第二趟!按照先前的步骤,交换堆顶与最后一个位置...如此循环直到所有数字成为有序排列。


简易学算法之堆排序

得到最后答案 有序序列:

遗留问题

最后,相信大家心里是隐隐作痛,我怎么知道开始把一个一维数列,变化成为一个大顶堆,然后才开始这么排序啊!这就是我文中一开始所提出的难题啦。而本篇至少让我们明白了堆排序是怎么进行的了!


哒哒哒哒


至于关于数列转化堆这个疑问,就交由下一姐妹篇,“二叉树”篇来说明吧!

以上是关于简易学算法之堆排序的主要内容,如果未能解决你的问题,请参考以下文章

重温基础算法内部排序之堆排序法

重温基础算法内部排序之堆排序法

排序算法总结之堆排序

算法排序之堆排序

排序算法之堆排序

排序算法之堆排序