目录
1、堆的概念
(1)是一颗完全二叉树
(2)父亲节点的优先级高于或低于左右孩子的优先级(值越大,优先级越高)
2、满二叉树
(1)除叶子节点之外,所有节点都有左右子树
(2)叶子节点都在最后一层
(3)每一层节点的个数:2^(l-1),l为层数
(4)叶子节点的个数:2^(h-1),h代表树高度
(5)非叶子节点的个数:2^(h-1)-1
(6)节点个数:2^(h)-1
3、完全二叉树(数组可以为完全二叉树)
二叉堆是一颗完全二叉树
完全二叉树:按照树的结构,从左到右依次排列
4、堆的性质 (假设索引从1开始)
(1)根节点没有父节点
(2)除根节点以外的任意节点(i) 的父亲节点的索引为: parent = i/2
(3)任意节点的左孩子节点的索引为:leftIndex = 2i
(4)任意节点的右孩子节点的索引为:rightIndex=(2i)+1
eg:如果根节点索引为0的位置上:
(1)除根节点以外的任意节点(i) 的父亲节点的索引为: parent = (i-1) /2
(2)任意节点的左孩子节点的索引为:leftIndex =(2i)+1
(3)任意节点的右孩子节点的索引为:rightIndex=(2i)+2
5、向堆中添加元素(上浮 float up)
1、添加元素52,添加到数组中索引为size的位置,然后更新size
2、从最后一个节点开始与父亲节点进行(优先级)比较,如果父亲节点的优先级低于当前节点,则进行交换
3、重复步骤二
4、直至根节点或父亲节点的优先级高于当前节点
//上浮,父亲节点的优先级大于自身,结束上浮
//已经上浮到root,结束上浮
private void floatUp(int i) {
//获取父节点
int currIndex=i;
int parentIndex =getparentIndex(currIndex);
//比较优先级,如果父索引优先级高,不进行交换
while (currIndex>0&&data[currIndex].compareTo(data[parentIndex])>0){
swap(this.data,currIndex,parentIndex);
currIndex=parentIndex;
parentIndex=getparentIndex(currIndex);
}
}
6、取出堆中优先级最高的元素(下沉swim)
最大堆中优先级最高的元素是索引为0的元素
1、使用最后一个元素替换索引为0元素,更新size
2、从索引为0的位置开始进行下沉操作:
(1)找到当前节点左右孩子节点中优先级较高的节点
(2)如果当前节点的优先级小于左右孩子节点中优先级较高的节点,则进行交换
(3)重复步骤二
(4)直至叶子节点或左右孩子节点中优先级较高的节点小于当前节点的优先级
private void swim() {
//判断是否为空
if (isEmpty()){
return;
}
//下沉从根节点开始
int curIndex =0;
int leftIndex =getleftIndex(curIndex);
int changeIndex=leftIndex;
//有左孩子的条件 leftIndex<this.size
while (leftIndex<this.size){
if (leftIndex+1<this.size&&data[leftIndex].compareTo(data[leftIndex+1])<0){
changeIndex=leftIndex+1;
}
if (data[curIndex].compareTo(data[changeIndex])>0){
break;
}
swap(this.data,curIndex,changeIndex);
curIndex=changeIndex;
leftIndex=getleftIndex(curIndex);
changeIndex=leftIndex;
}
}
7、堆的时间复杂度分析
从上面的分析图,可以得出,无论进行上浮还是下沉操作,最多交换的次数为整棵树的高度h
O(h) = O(logn)
8、Heapify和Replace
replace :取出最大元素后,放入一个新元素
实现方式:直接将堆顶元素替换成新元素,然后进行sift down操作
//replace操作,取出优先级最高的元素,放入一个新元素(让新元素替换索引为0的元素)
public void replace(T newEle){
this.data[0]=newEle;
swim();
}
heapify:将任意数组整理成堆的形状
实现方式:从最后一个元素的父亲节点开始进行调整(sift down) ,直到根节点
1、找到最后一个元素的父亲节点(size-1-1)/2
2、循环进行下沉操作, 直至根节点
//heapify:将任意数组整理成堆
/*
1、依次添加
2、从最后元素的父亲节点开始依次进行swim操作,直到root
*/
public void heapify(){
if (this.data==null&&this.data.length==0){