二叉堆的定义就不多说了,我们主要介绍二叉堆的自我调整,二叉堆分为最大堆,最小堆。
二叉堆的储存方式是数组,所以其左子下标为 2*parent+1;右子为2*parent+2;
搞明白了这个,首先介绍插入一个数,插入位置是二叉堆最后一个位置;将其排序,
则 我们使用上浮调整最小堆
public static void upAdjust(int[] array) {
int childIndex = array.length-1;//最后一个子值的下标
int parentIndex = (childIndex-1)/2;//找到其父值下标
int temp = array[childIndex]; // temp保存插入的叶子节点值,用于最后的赋值
while (childIndex > 0 && temp < array[parentIndex])//新值没上升到根或小于父值
{
//无需真正交换,单向赋值即可
array[childIndex] = array[parentIndex];//将父值变成子值
childIndex = parentIndex;//让子值替代父值,使用交换下标
parentIndex = (parentIndex-1) / 2;//新的父值
}
array[childIndex] = temp;最后跳出循环,放入子值
}
最大堆的方法同理不过多写了
接下来我们将一个无规则的树进行排列
使用下沉的方法
public static void downAdjust(int[] array, int parentIndex, int length) {//传入数组,父值的下标,数组长度
int temp = array[parentIndex]; // temp保存父节点值,用于最后的赋值
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;//结束,放入值
}
public static void buildHeap(int[] array) {
// 从最后一个非叶子节点开始,依次下沉调整
for (int i = (array.length-2)/2; i >= 0; i--) {
downAdjust(array, i, array.length);
}
}
接下来就是总代码了
package tree;
import java.util.Arrays;
public class HeapOperator {
/**
* 上浮调整
* @param array 待调整的堆
*/
public static void upAdjust(int[] array) {
int childIndex = array.length-1;
int parentIndex = (childIndex-1)/2;
// temp保存插入的叶子节点值,用于最后的赋值
int temp = array[childIndex];
while (childIndex > 0 && temp < array[parentIndex])
{
//无需真正交换,单向赋值即可
array[childIndex] = array[parentIndex];
childIndex = parentIndex;
parentIndex = (parentIndex-1) / 2;
}
array[childIndex] = temp;
}
/**
* 下沉调整
* @param array 待调整的堆
* @param parentIndex 要下沉的父节点
* @param length 堆的有效大小
*/
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;
}
/**
* 构建堆
* @param array 待调整的堆
*/
public static void buildHeap(int[] array) {
// 从最后一个非叶子节点开始,依次下沉调整
for (int i = (array.length-2)/2; i >= 0; i--) {
downAdjust(array, i, array.length);
}
}
public static void main(String[] args) {
int[] array = new int[] {1,3,2,6,5,7,8,9,10,0};
upAdjust(array);
System.out.println(Arrays.toString(array));
array = new int[] {7,1,3,10,5,2,8,9,6};
buildHeap(array);
System.out.println(Arrays.toString(array));
}
}
结果分别是 [0, 1, 2, 6, 3, 7, 8, 9, 10, 5] 和[1, 5, 2, 6, 7, 3, 8, 9, 10]