在上一篇漫画中,小灰介绍了 二叉堆 这样一种强大的数据结构:

漫画:什么是二叉堆?(修正版)

那么,这个二叉堆怎样来使用呢?我们这一期将会详细讲述。

让我们回顾一下二叉堆和最大堆的特性:

1.二叉堆本质上是一种完全二叉树

2.最大堆的堆顶是整个堆中的最大元素

当我们删除一个最大堆的堆顶(并不是完全删除,而是替换到最后面),经过自我调节,第二大的元素就会被交换上来,成为最大堆的新堆顶。

正如上图所示,当我们删除值为10的堆顶节点,经过调节,值为9的新节点就会顶替上来;当我们删除值为9的堆顶节点,经过调节,值为8的新节点就会顶替上来.......

由于二叉堆的这个特性,我们每一次删除旧堆顶,调整后的新堆顶都是大小仅次于旧堆顶的节点。那么我们只要反复删除堆顶,反复调节二叉堆,所得到的集合就成为了一个有序集合,过程如下:

删除节点9,节点8成为新堆顶:

删除节点8,节点7成为新堆顶:

删除节点7,节点6成为新堆顶:

删除节点6,节点5成为新堆顶:

删除节点5,节点4成为新堆顶:

删除节点4,节点3成为新堆顶:

删除节点3,节点2成为新堆顶:

到此为止,我们原本的最大堆已经变成了一个从小到大的有序集合。之前说过二叉堆实际存储在数组当中,数组中的元素排列如下:

由此,我们可以归纳出堆排序算法的步骤:

1. 把无序数组构建成二叉堆。

2. 循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。

public class HeapSort {/*** 下沉调整* @param array     待调整的堆* @param parentIndex    要下沉的父节点* @param parentIndex    堆的有效大小*/public static void downAdjust(int[] array, int parentIndex, int length) {// temp保存父节点值,用于最后的赋值int temp = array[parentIndex];int childIndex = 2 * parentIndex + 1;while (childIndex < length) {// 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子if (childIndex + 1 < length && array[childIndex + 1] > array[childIndex]) {childIndex++;}// 如果父节点小于任何一个孩子的值,直接跳出if (temp >= array[childIndex])break;//无需真正交换,单向赋值即可array[parentIndex] = array[childIndex];parentIndex = childIndex;childIndex = 2 * childIndex + 1;}array[parentIndex] = temp;}/*** 堆排序* @param array     待调整的堆*/public static void heapSort(int[] array) {// 1.把无序数组构建成二叉堆。for (int i = (array.length-2)/
2; i >= 0; i--) {downAdjust(array, i, array.length);}System.out.println(Arrays.toString(array));// 2.循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。for (int i = array.length - 1; i > 0; i--) {// 最后一个元素和第一元素进行交换int temp = array[i];array[i] = array[0];array[0] = temp;// 下沉调整最大堆downAdjust(array, 0, i);}}public static void main(String[] args) {int[] arr = new int[] {1,3,2,6,5,7,8,9,10,0};heapSort(arr);System.out.println(Arrays.toString(arr));}}

二叉堆的节点下沉调整(downAdjust 方法)是堆排序算法的基础,这个调节操作本身的时间复杂度是多少呢?

假设二叉堆总共有n个元素,那么下沉调整的最坏时间复杂度就等同于二叉堆的高度,也就是O(logn)

我们再来回顾一下堆排序算法的步骤:

1. 把无序数组构建成二叉堆。

2. 循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。

第一步,把无序数组构建成二叉堆,需要进行n/2次循环。每次循环调用一次 downAdjust 方法,所以第一步的计算规模是  n/2 * logn,时间复杂度O(nlogn)

第二步,需要进行n-1次循环。每次循环调用一次 downAdjust 方法,所以第二步的计算规模是 (n-1) * logn ,时间复杂度 O(nlogn)

两个步骤是并列关系,所以整体的时间复杂度同样是 O(nlogn)

—————END—————

漫画:什么是堆排序?相关推荐

  1. 漫画:有趣的海盗问题 (完整版)

    -----  第二天  ----- 海盗分金币问题: 有5个海盗,获得了100枚金币,于是他们要商量一个方法来分配金币.商议方式如下: 1. 由5个海盗轮流提出分配方案. 2. 如果超过半数海盗(包括 ...

  2. 漫画:什么是LRU算法?

    本期封面作者:A17 -----  两个月前  ----- 用户信息当然是存在数据库里.但是由于我们对用户系统的性能要求比较高,显然不能每一次请求都去查询数据库. 所以,小灰在内存中创建了一个哈希表作 ...

  3. 今晚,咱们就聊聊堆排序吧!

    作者:小灰 来自:程序员小灰(ID:chengxuyuanxiaohui) 在上一篇漫画中,小灰介绍了 二叉堆 这样一种强大的数据结构: 漫画:什么是二叉堆?(修正版) 那么,这个二叉堆怎样来使用呢? ...

  4. python遍历数组冒泡排序_经典排序算法(冒泡排序,选择排序,插入排序,快速排序,堆排序)python实现...

    最近在复习经典排序算法,自己用python也实现了一下,这里不会涉及到原理(因为网上方法已经很详细啦),就把函数贴上来,可以让大家自己试着运行下,再结合别处的原理也可以更好地理解它们的实现. 如果有错 ...

  5. 【算法入门漫画】:“排序算法” 大总结

    冒泡排序: 漫画:什么是冒泡排序? 选择排序: 漫画:什么是选择排序? 插入排序: 漫画:什么是插入排序? 此外还有冒泡排序的变种,鸡尾酒排序: 漫画:什么是鸡尾酒排序? 第三梯队的排序算法有什么共同 ...

  6. 漫画:什么是优先队列

    转载自  漫画:什么是优先队列 在之前的漫画中,我们介绍了二叉堆和堆排序.没看过的小伙伴可以看一看前文: 漫画:什么是二叉堆?(修正版) 漫画:什么是堆排序? 这一次,我们来讲一讲二叉堆的另外一个应用 ...

  7. 算法与数据结构 (三) 二叉树的简单应用 二叉查找树,二叉堆排序

    一  二叉查找树 二叉查找树又叫二叉排序树,是为了解决查找的效率问题.正常情况下查找一个元素,需要O(n)的代价,但是如果查找元素有顺序,有序数组:可以用二分查找降低到 lgn 代价,但是有序链表的代 ...

  8. c++ 二维数组 排序_漫画:“排序算法” 大总结

    ​冒泡排序: 漫画:什么是冒泡排序?​mp.weixin.qq.com 选择排序: 漫画:什么是选择排序?​mp.weixin.qq.com 插入排序: 漫画:什么是插入排序?​mp.weixin.q ...

  9. 漫画:有趣的 “切蛋糕“ 问题

    -----  第二天  ----- 举个例子: 我们有5块蛋糕, 蛋糕的大小分别是 5,17,25,3,15 我们有7位顾客, 他们的饭量分别是 2,5,7,9,12,14,20 (每个蛋糕大小和顾客 ...

  10. 《漫画算法》终于出电子书了!

    今年5月,小灰出版了<漫画算法>这本纸质书. 在今年年中,本书获得[京东科技新书畅销榜]第1名,[京东科技畅销榜]第4名,非常感谢大家的支持! 但是有一点美中不足,小灰的这本<漫画算 ...

最新文章

  1. USB获取图像实时处理
  2. 2018-3-14智能算法(文章--优化问题的智能算法及其哲学内涵)笔记一(什么是优化问题)
  3. 卷积神经网络为什么能称霸计算机视觉领域?
  4. Hive查询结果输出文件
  5. JavaScript单行代码
  6. 如何做好性能压测(一)丨压测环境设计和搭建
  7. LeetCode 编辑距离 II(DP)
  8. 麦块不显示服务器,为什么开不了服务器啊!
  9. “企业知识产权管理与预警”培训活动在省技术产权交易市场成功举办
  10. for 循环新的写法==列表解析
  11. 耳挂式蓝牙耳机原理_耳挂式蓝牙耳机项目总结分析报告
  12. UbuntuSkills
  13. acr122 java,ACR122U使用教程
  14. 生态系统类型空间分布数据/土地利用数据/植被类型数据/NPP数据/土壤侵蚀数据/土壤质地分类/降雨量栅格数据
  15. 入职半年后,我升到了管理岗
  16. 输入法半角和全角的快捷转换_Windows 10—禁用Ctrl+Space输入法非输入法切换
  17. (附源码)springboot闲置衣物捐赠系统 毕业设计 021009
  18. 【论文翻译】Playing Atari with Deep Reinforcement Learning
  19. python使用selenium + PhantomJs搭建的简单漫画爬虫工具
  20. 云之讯融合通讯开放平台_提供融合语音,短信,VoIP,视频和IM等通讯API及SDK。...

热门文章

  1. 5.27 indeed 第三次网测
  2. 操作Visual Studio 2010中的SQL Server数据库比较工具
  3. Hyperledger Fabric 实战(八):couchdb 丰富查询 selector 语法
  4. ActiveMQ笔记(二)
  5. AES算法,DES算法,RSA算法JAVA实现
  6. Python数据分析(二): Numpy技巧 (3/4)
  7. 2014中国高校SAS数据分析大赛拉开帷幕
  8. Asp.net Boilerplate之AbpSession扩展
  9. Java实现mysql的读写分离
  10. myeclipse 报内存不足的解决方法