2019独角兽企业重金招聘Python工程师标准>>>

Java实现最小堆一

堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。

  最大堆和最小堆是二叉堆的两种形式。

  最大堆结点的键值是所有堆结点键值中最大者。

  最小堆结点的键值是所有堆结点键值中最小者。

就像下面这棵树一样。

这棵二叉树有一个特点,就是所有父结点都比子结点要小(注意:圆圈里面的数是值,圆圈上面的数是这个结点的编号,此规定仅适用于本节)。符合这样特点的完全二叉树我们称为最小堆。反之,如果所有父结点都比子结点要大,这样的完全二叉树称为最大堆。

那这一特性究竟有什么用呢? 假如有14个数分别是99、5、36、7、22、17、46、12、2、19、25、28、1和92。请找出这14个数中最小的数,请问怎么办呢?最简单的方法就是将这14个数从头到尾依次扫一遍,用一个循环就可以解决。这种方法的时间复杂度是O(14)也就是O(N)。

for(i=1;i<=14;i++)
{if(a[i]<min){min=a[i];}
}

现在我们需要删除其中最小的数,并增加一个新数23,再次求这14个数中最小的一个数。请问该怎么办呢?只能重新扫描所有的数,才能找到新的最小的数,这个时间复杂度也是O(N)。假如现在有14次这样的操作(删除最小的数后并添加一个新数)。那么整个时间复杂度就是O(142)即O(N2)。

那有没有更好的方法呢?堆这个特殊的结构恰好能够很好地解决这个问题。

首先我们先把这个14个数按照最小堆的要求(就是所有父结点都比子结点要小)放入一棵完全二叉树,就像下面这棵树一样。

很显然最小的数就在堆顶,假设存储这个堆的数组叫做h的话,最小数就是h[1]。接下来,我们将堆顶的数删除,并将新增加的数23放到堆顶。显然加了新数后已经不符合最小堆的特性,我们需要将新增加的数调整到合适的位置。那如何调整呢?

向下调整!我们需要将这个数与它的两个儿子2和5比较,并选择较小一个与它交换,交换之后如下

我们发现此时还是不符合最小堆的特性,因此还需要继续向下调整。于是继续将23与它的两个儿子12和7比较,并选择较小一个交换,交换之后如下

到此,还是不符合最小堆的特性,仍需要继续向下调整直到符合最小堆的特性为止。

我们发现现在已经符合最小堆的特性了。

综上所述,当新增加一个数被放置到堆顶时,如果此时不符合最小堆的特性,则将需要将这个数向下调整,直到找到合适的位置为止,使其重新符合最小堆的特性。

我们刚才在对23进行调整的时候,竟然只进行了3次比较,就重新恢复了最小堆的特性。现在最小的数依然在堆顶为2。之前那种从头到尾扫描的方法需要14次比较,现在只需要3次就够了。

现在每次删除最小的数并新增一个数,并求当前最小数的时间复杂度是O(3),

假如现在有1亿个数(即N=1亿),进行1亿次删除最小数并新增一个数的操作,使用原来扫描的方法计算机需要运行大约1亿的平方次,而现在只需要1亿*log1亿次,即27亿次。假设计算机每秒钟可以运行10亿次,那原来则需要一千万秒大约115天!而现在只要2.7秒。是不是很神奇,再次感受到算法的伟大了吧。

说到这里,如果只是想新增一个值,而不是删除最小值又该如何操作呢?即如何在原有的堆上直接插入一个新元素呢?只需要直接将新元素插入到末尾,再根据情况判断新元素是否需要上移,直到满足堆的特性为止。如果堆的大小为N(即有N个元素),那么插入一个新元素所需要的时间也是O(logN)。例如我们现在要新增一个数3。

先将3与它的父结点25比较,发现比父结点小,为了维护最小堆的特性,需要与父结点的值进行交换。交换之后发现还是要比它此时的父结点5小,因此需要再次与父结点交换。至此又重新满足了最小堆的特性。向上调整完毕后如下。

如何建立这个堆,见下篇http://my.oschina.net/xinxingegeya/blog/705409

=======END=======

转载于:https://my.oschina.net/xinxingegeya/blog/703801

Java实现最小堆一相关推荐

  1. java 链表 最小堆优先级队列_关于Java集合的小抄

    List ArrayList 以数组实现.节约空间,但数组有容量限制.超出限制时会增加50%容量,用System.arraycopy()复制到新的数组,因此最好能给出数组大小的预估值.默认第一次插入元 ...

  2. java 链表 最小堆优先级队列_Java集合细说

    Java集合类图关系思维导图,带对号标志的为线程安全类. 各集合类相关区别详解: 0x01:List Set Map Queue的区别 List有序,可以多个元素引用相同的对象 Set无序,不重复,不 ...

  3. java 最小堆_Java最小堆实现

    package boke.heap1; /** * 堆结点 * * @since jdk1.5及其以上 * @author 毛正吉 * @version 1.0 * @date 2010.05.24 ...

  4. Java最小堆解决TopK问题

    转载自  Java最小堆解决TopK问题 TopK问题是指从大量数据(源数据)中获取最大(或最小)的K个数据. TopK问题是个很常见的问题:例如学校要从全校学生中找到成绩最高的500名学生,再例如某 ...

  5. java队列优先级_优先级队列-Java的PriorityQueue与最小堆有何不同?

    来自Java文档 表示为平衡二进制堆的优先级队列:queue [n]的两个子级是queue [2 * n + 1]和queue [2 *(n + 1)]. 优先级队列由比较器或元素的自然顺序进行排序. ...

  6. java 最小堆_堆排序 最大堆 最小堆 Java 实现

    堆 一点疑惑,堆排序是就地排序,所以空间复杂度是 O(1).但是,比如我有一个数组,建立一个最小堆,然后每次取出最小堆的顶点.建立最小堆需要额外空间? 不深究了,归并排序需要额外空间. 堆是完全二叉树 ...

  7. 堆之最小堆、最大堆(java实现)

    文章目录 堆 图解 最大堆的api设计 最大堆代码实现 最小代码实现 堆 定义:堆是树型的一对多的数据结构,使用数组实现 对应完全二叉树 每个节点大于等于或者小于等于它的子节点 二叉树: 每个非叶子节 ...

  8. merge k sorted lists java_LeetCode 第23题 Merge k Sorted Lists【分而治之】【最小堆】(Java)...

    这道题的题目是合并k个有序的链表,标定难度为Hard,详细需求: 合并k个有序的链表,返回一个新的有序链表. 例子: Input: 1->4->5, 1->3->4, 2-&g ...

  9. 《徐徐道来话Java》:PriorityQueue和最小堆

    在讲解PriorityQueue之前,需要先熟悉一个有序数据结构:最小堆. 最小堆是一种经过排序的完全二叉树,其中任一非终端节点数值均不大于其左孩子和右孩子节点的值. 可以得出结论,如果一棵二叉树满足 ...

最新文章

  1. APICloud学习第二天——操作云数据库
  2. go语言初体验(流程控制、range遍历、函数、结构体、面向对象)
  3. IIS7、IIS8添加net.tcp协议报错 未将对象引用设置到对象的实例。
  4. datatable 查询_2020年浙江注册会计师成绩查询预告
  5. IIS上部署Net.Core
  6. 织梦mysql安装教程视频教程_织梦DedeCMSV6系统安装步骤教程
  7. java pdf无法加载_java - 试图使用iText7合并来合并pdf,但是当我打开最终的合并pdf时,它说无法加载pdf文档 - SO中文参考 - www.soinside.com...
  8. GDAL读取S-57海图数据中文属性值乱码问题解决
  9. Hive 分组取Top N
  10. 心电图分析软件_家用心电图机,一键出报告,让你在家就能看懂心电图!
  11. 游戏公司2022秋招记录
  12. Win7 计算机中丢失api-ms-win-core-path-|1-1-0.dll
  13. 京东店铺怎么运营 掌握这些京东运营知识很有必要!
  14. ubuntu系统下快速安装谷歌浏览器(图文教程)
  15. python中哈希是什么意思_利用Python如何生成hash值示例详解
  16. 【5G核心网】5GC核心网之网元AMF
  17. python斜杠作用_Python中正反斜杠(‘/’和‘\’)的意义与用法
  18. 智能语音将成下一代人机交互新入口
  19. MySQL空间函数ST_Distance_Sphere()的使用
  20. requests用法之爬取豆瓣排行

热门文章

  1. - 运算符(C# 参考)
  2. 用户一亿的网易新闻客户端质量如何?
  3. 两台电脑之间用网线之间传文件
  4. SQL Server 2008 清空删除日志文件 130G日志 10秒内变10M .
  5. FTP(虚拟用户,并且每个虚拟用户可以具有独立的属性配置)
  6. RN中布局样式的写法
  7. java线程学习-Thread.currentTread().getName()和this.getName()的区别
  8. ”舍得“大法:把自己的优点当缺点倒出去
  9. Chapter 17 高级进程间通信
  10. [MySQL FAQ]系列 -- 为何授权不对