二叉堆的定义:
二叉堆是一颗完全二叉树。
完全二叉树:把元素顺序排列成树的形状。这里的顺序是自上而下,从左到右。
最大堆:
最大堆是一种特殊的二叉堆,顶部为最大元素,并且每个子树的根节点大于等于左右孩子节点。
我们可以用数组来存放最大堆的每个元素,如下图:
其中,根节点的下标为 0 ,每个子树中父亲节点和左右孩子节点的下标关系为: parent(i) = (i - 1)/2;leftChild(i) = 2*i + 1;rightChild(i) = 2*i + 2。
最大堆的结构:
泛型必须具有可比性。
最大堆的父亲节点和左右孩子下标的关系:
向最大堆添加元素:
思路:首先向数组的末尾新增元素,然后比较新元素(末尾元素)的值与其父亲元素的值,如果前者大于等于后者,则不符合最大堆的规则,需要上浮操作(交换二者的值),上浮操作完成之后,继续对比,直到符合最大堆规则为止。
向最大堆取出元素(最大值):
最大堆只能取出最大值,因为它只要满足父亲节点大于等于左右孩子就行了,所以左右孩子位置可以互换,即无法通过下标找到其他节点,这就是最大堆的限制。
思路:先在数组的头部找出最大元素,然后让数组的末尾元素替换头部元素,并且删除末尾元素。然后让头节点和其左右孩子中较大值进行比较,如果前者小于后者,则需要下沉(交换二者的值)。下沉操作完成之后,继续对比,直到符合最大堆规则为止。
向最大堆中取出最大元素后,放入一个新元素:
思路:找到数组的头部的,将新元素替换为头部元素,然后执行下沉操作。
将任意数组整理成最大堆的形状:
思路:使用构造函数,将传入的数组转换为集合并赋值给 data,然后找到最后一个非叶子的节点(最后一个元素的父亲节点),即 index = parent(arr.length - 1),从最后一个非叶子结点开始往上遍历,执行下沉操作。因为下沉操作会涉及到左右孩子,所以已经能够比较到所有元素了。
将最大堆封装成优先队列PriorityQueue:
优先队列:普通队列为先进先出,然而优先队列出队列却是优先度最高的元素,
优先度是可以根据业务自定义的。我们就可以约定元素值越大,优先级越高。故最大堆可以很容易的符合,因为它的最大元素就是数组首位。