堆和优先级队列1:堆概念和构造过程

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆和优先级队列1:堆概念和构造过程相关的知识,希望对你有一定的参考价值。

堆是java核心基础中的重要内容,同时也是算法中的重要内容,幸运的是堆相关的算法一般说清楚解决方法就行了,不需要手写。原因是如果自己构造堆,一小时也写不完,如果调用java自带的,很多时候我们也不记得该怎么用,因此面试官一般不会难为人。

1、堆的概念

堆的概念

堆是将一组数据按照完全二叉树的存储顺序,将数据存储在一个一维数组中的结构。
堆有两种结构,一种称为大顶堆,一种称为小顶堆,如下图。
小顶堆:任意结点的值均小于等于它的左右孩子,并且最小的值位于堆顶,即根节点处。
大顶堆:任意结点的值均大于等于它的左右孩子,并且最大的值位于堆顶,即根节点处。
 

 

既然是将一组数据按照树的结构存储在一维数组中,那么父子之间关系的建立就很重要了。
假设一个节点的下标为i。
1、当i = 0时,为根节点。
2、当i>=1时,父节点为(i - 1)/2

2.堆的构造过程 

使用数组构建堆时,就是先按照层次将所有元素依次填入二叉树中,使其成为二叉树,然后再不断调整,最终使其符合堆结构。

以下面这个例子来建堆,

 

int arr[10] = {12,23,54,2,65,45,92,47,204,31}
arr.size() = 10;

先看一下一次调整:
1、int i = (size - 2)/2 = 4找到数组中的4号下标。
65大于其孩子,满足大堆性质,所以不用交换。

 

 

2、i= i-1;然后用2和其孩子比较,2和204交换。交换之后满足大堆

 

 

 3、54和其孩子比较,54和92交换。交换之后满足大堆性质

 

4、23和其孩子比较,23和204交换

交换完之后,它的子树却不满足了,所以还需调整它的子树。 

 

5、12和204交换。

 

 

 3.插入和删除元素

在堆中插入一个元素,因为本身堆是建好的,所以满足性质,插入一个在树的最后,只需要顺着这条支路做一次调整就好了,不过这次不需要向下调整了,因为父节点肯定是大于子节点的。

如图,如果插入的节点大于它的父节点,发生交换是肯定不会影响其子树的,因为父节点本身就大于它的子节点,更何况交换后的节点是大于父节点的。所以,这里只需要一次简单的向上调整就可以完成。

删除
因为堆本身就是一种特殊的结构,所以一般对堆中的数据进行操作都是针对堆顶的元素,即针对最大值或最小值,比如哈夫曼树就用堆的结构来实现,因为每次要找出最小的两个数。
所以我们删除的时候,一般也是删除堆顶那个最小或最大的值,但是如果直接删掉堆顶,整个堆的结构被破坏了,必须重现建堆,这样无疑效率非常低,所以采用将堆中最后一个元素和堆顶元素进行替换,然后删除堆中最后一个元素。
  

 

 

 

 

 

以上是关于堆和优先级队列1:堆概念和构造过程的主要内容,如果未能解决你的问题,请参考以下文章

数据结构 Java 版堆和优先级队列(超详解)

数据结构 Java 版堆和优先级队列(超详解)

笔记2. 堆(优先队列)

堆和优先队列

堆和堆的应用:堆排序和优先队列

STL之堆和优先队列