通俗解释大顶堆和小顶堆
Posted 元之田
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通俗解释大顶堆和小顶堆相关的知识,希望对你有一定的参考价值。
- 基础数据结构
想象我们有一个数组,数组中有0到9,10个元素。
我们按照顺序将一颗二叉树画出来。
- 如果我们将数据填入数组之中,树种相应节点的值也将填入。
这里我们观察到,树中节点之间存在如下关系:
假设当前节点的下标为i ——
节点的左子节点的下标为:2 * i + 1;
节点的右子节点的下标为:2 * i + 2;
- 大顶堆和小顶堆
我们知道大顶推满足的条件是每一个父节点都比子节点大。
那么我们应该如何通过调换节点的位置来构建这样的数据结构呢?
我们取这个树的一个片段,假设数据为2,1,3。那么我们需要进行的一个操作是heapify-down,通过将2和1与3中比较大的节点替换位置,以此来满足条件。
这是我们调整的过程。
我们观察可知,对于一颗长度为10的树(堆),我们自上而下只需要将节点4,3,2,1,0分别进行heapify既可以满足大顶堆的满足条件。
建堆代码:
//build max heap
public void buildHeap(int[] arr)
for(int i = arr.length/2; i >=0; i--)
adjust(arr, i);
但这里有需要注意的地方。举个例子,如果我们对节点1进行heapify,节点1将与节点3和4中值比较大的节点交换值。这样的话,节点3或4其中之一的值就会发生改变,为了满足堆的条件,因此我们需要再对替换顺序后的节点进行一次heapify,这也是为什么heapify中存在递归的原因。
对于大顶堆,我们是自下而上进行建堆,这样我们把最大值推上0的位置。
注意我们的heapify是自上而下将大的元素向下转移。
public void adjust(int[] arr, int i)
int maxIndex = i;
int len = arr.length;
if(2*i+1 < len && arr[2*i+1] > arr[maxIndex]) maxIndex = 2*i+1;
if(2*i+2 < len && arr[2*i+2] > arr[maxIndex]) maxIndex = 2*i+2;
if(maxIndex != i)
swap(arr, maxIndex, i);
adjust(arr, maxIndex);
-
新元素的加入。
当有新元素加入堆中时,我们需要重新进行heapify的操作,我们只需要把元素加入到堆的末尾,然后重新进行heapify即可。
在应用中,我们往往需要找到第k大的数字,只需要在建好大顶堆后,判断新元素是否比堆顶元素小即可,如果小即替换,再重新heapify-down。 -
除此之外,也有heapify-up进行自下而上的调整操作,这些根据具体需要可以自行构建。
在java中我们可以使用PriorityQueue来解决涉及堆的问题。
以上是关于通俗解释大顶堆和小顶堆的主要内容,如果未能解决你的问题,请参考以下文章