1.简介
二叉堆本质上是一棵完全二叉树,它分为最大堆和最小堆。最大堆就是它里面的任何一个父节点的值,都大于或者等于它的左、右孩子节点的值。最小堆就是其中的任何一个父节点的值都小于或者等于它左、右孩子节点的值。二叉堆中的根节点叫做堆顶,最大堆和最小堆决定了:最大堆的堆顶是整个堆中最大的元素,最小堆的堆顶是整个堆中最小的元素。
2.二叉堆的代码实现
二叉堆虽然是一棵完全二叉树,但是它的存储方式并不是链式存储,而是顺序存储,也就说,夜叉对中的所有节点都存储在数组中。假设父节点的下表为parent,则她的左孩子的下标为2parent+1,右孩子的下表为2parent+2
2.1 构建堆
public static void buildHead(int[] array){
//从最后一个非叶子节点开始,依次做“下沉”调整
for(int i = (array.length - 2) / 2; i >= 0; i--){
downAdjust(array,i,array.length);
}
}
2.2 上浮调整
public static void upAjust(int[] array){
int childIndex = array.length - 1;
int parentIdex = (childIndex - 1) / 2;
//temp保存插入的叶子节点的值,用于最后的赋值
int temp = array[childIndex];
while(childIndex > 0 && temp < array[parentIdex]){
//无须真正交换,单向赋值即可
array[childIndex] = array[parentIdex];
childIndex = parentIdex;
parentIdex = (parentIdex - 1) / 2;
}
array[childIndex] = temp;
}
2.3 下沉调整
public static void downAdjust(int[] array,int parentIndex,int length){
//temp保存父节点的值,用于最后的赋值
int temp = array[parentIndex];
int childIndex = 2 * parentIndex + 1;
while(childIndex < length){
//如果有右孩子,而且右孩子小于左孩子的值,则定位到右孩子
if(childIndex + 1 < length && array[childIndex + 1] < array[childIndex]){
childIndex++;
}
//如果父节点小于任何一个孩子的值,则直接跳出
if(temp <= array[childIndex])
break;
//无须真正交换,单向赋值即可
array[parentIndex] = array[childIndex];
parentIndex = childIndex;
childIndex = 2 * childIndex + 1;
}
array[parentIndex] = temp;
}
2.4 测试方法
public static void main(String[] args){
int[] array = {1,3,2,6,5,7,8,9,10,0};
upAjust(array);
System.out.println(Arrays.toString(array));
array = new int[]{7,1,3,10,5,2,8,9,6};
buildHead(array);
System.out.println(Arrays.toString(array));
}