今晚,咱们就聊聊堆排序吧!
作者:小灰
来自:程序员小灰(ID:chengxuyuanxiaohui)
在上一篇漫画中,小灰介绍了 二叉堆 这样一种强大的数据结构:
漫画:什么是二叉堆?(修正版)
那么,这个二叉堆怎样来使用呢?我们这一期将会详细讲述。
让我们回顾一下二叉堆和最大堆的特性:
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—————
长按订阅同类文章
一起搬砖的点个赞
今晚,咱们就聊聊堆排序吧!相关推荐
- 十大经典排序算法详解(三)-堆排序,计数排序,桶排序,基数排序
养成习惯,先赞后看!!! 你的点赞与关注真的对我非常有帮助.如果可以的话,动动手指,一键三连吧!!! 十大经典排序算法-堆排序,计数排序,桶排序,基数排序 前言 这是十大经典排序算法详解的最后一篇了. ...
- 【经济学_04】晨读:保险的实质 特效药 医疗膨胀 保险的发明
文章目录 晨读:保险的实质 情景 认知 本质 Q1:那么保险是资产还是负债呢? Q2:富人也喜欢保险? 对于企业来说保险的好处 无时无刻都在接触保险 为什么说,越穷的人越需要配保险 保险特点 特点1: ...
- 知乎16万赞:“你对空姐提过最奇怪的要求是什么?”回答暴露文化水平
01 前段时间,刷到一个很有意思的知乎问题:"你对空姐提出过最奇怪的要求是什么?" 其中有个回答获赞最高,有16.5万人点了赞同. 答主"牛布尼茨"说,他爷爷曾 ...
- TikTok 还有机会吗?
阅读本文大概需要 1.29 分钟. 在开年的时候,我们星球跟 TikTok 官方合作,举办了一次挑战活动,其实去年也举办过类似的,由我们组局,然后 TikTok 官方人员带队.主要考虑到星球里面不少人 ...
- 【今晚7点】:圆桌PI回归 继续聊聊开源的故事
点击上方"LiveVideoStack"关注我们 圆桌PI,是LiveVideoStack公开课的形式之一,我们会约上几位专家进行线上的虚拟圆桌讨论,分享观点,探讨热点话题,回答听 ...
- 今晚8点和 Conflux 张元杰聊聊,在中国做 Web3 的机会在哪里?
关于 Web3,你可能看到了这样的现象和论断: 受限于强监管,在国内做 Web3 完全没有机会,只能去海外.一度我们可以看到一个壮观的场景,国内 Web2 大厂的精英们,纷纷奔赴海外,作为国人的首选新 ...
- 清华大学计算机吴教授开讲啦,开讲啦!吴建平院士今晚十点半CCTV-1聊聊互联网二三事儿...
原标题:开讲啦!吴建平院士今晚十点半CCTV-1聊聊互联网二三事儿 1 月 27 日 周 六 今晚十点半 中国工程院院士.清华大学计算机科学与技术系主任.CERNET专家委员会主任吴建平教授做客中央电 ...
- 【今晚七点】:对话快手张亮——聊聊音视频出海
点击上方"LiveVideoStack"关注我们 自疫情以来,人们的生活.工作.出行都受到了一定限制,这也使得大家对线上社交及办公的需求不断提升,推动音视频行业快速发展的同时也带来 ...
- 聊聊Service Mesh:linkerd
[编者的话]随着企业逐渐将传统的单体应用向微服务或云原生应用的转变,虽然微服务或者云原生应用能给企业带来更多的好处,但也会带来一些具有挑战的问题,如怎么管理从单体应用转向微服务所带来的服务间通讯的复杂 ...
最新文章
- 践行科技向善,腾讯Light 把光引向厦门
- python比较数据库表今天跟前一天数据增量,Python 生产环境Mysql数据库增量备份脚本...
- antd 侧边栏如何自适应高度
- 自动构建工具Grunt
- 第一行代码学习笔记第八章——运用手机多媒体
- CSS 如何设置垂直居中
- 知乎高赞:这个开挂神器简直了!
- java while等待 yeild_Java中run(), start(), join(), wait(), yield(), sleep()的使用
- Visual Studio 2008 Service Pack 1 - BETA发布
- MACOS,应用签名后就崩溃?
- crackme用来测试程序设计人员的逆向工程技能的小程序。
- 系统篇: fstab 文件详解
- 绝地反击 我的战胜贫困的经历01 转载 整理
- KVM虚拟化的概述和部署
- 免费好用的征集工具 | 玩转穿搭征集、好物征集、攻略征集
- 花了10分钟,终于弄懂了特征值和特征向量到底有什么意义
- [案例4-2]饲养员喂养动物
- javascript原型、原型链神图
- 全球及中国犬淋巴瘤治疗行业研究及十四五规划分析报告
- PANSS 阳性与阴性症状量表
热门文章
- 二分图HK算法[数论+二分图最大独立集]:Lightoj1356
- codeforces数学1600day6[CodeForces - 1029C多区间交+枚举,CodeForces 992C[数学公式推导],CodeForces 992B[质因数分解+暴力枚举]]
- html盒子宽高,css盒子模型之宽度和高度
- 抢红包算法 c语言,红包分配算法,抢红包算法
- POJ2932Coneology(计算几何、平面扫描)
- 并查集(压缩路径+按秩排序)
- java字节流6_JavaIO流之字节流
- 在目前大数据时代下,怎么能成为一名合格的数据分析师
- mysql找安装路经,更改密码
- java中父类与子类的关系以及使用