关键点:
1)堆分为小根堆和大根堆,根结点大于子结点叫堆,反之为小根堆
2)堆由数组构建而成
3)二叉堆中子结点与父结点的关系:
· 父结点下标 = (子结点下标-1) / 2
· 左子结点下标 = 父结点下标 * 2 + 1
· 右子结点下标 = 父结点下标 * 2 + 2
4) 对于堆的操作有插入、移除、调整
大根堆的java实现:
public class MaxHeap {
private int[] heap;
/**
* 传入数据构造堆
* @param data
*/
public MaxHeap(int[] data) {
heap = data;
buildHeap();
}
private void buildHeap() {
for(int i=0; i<heap.length; i++) {
adjustUpHeap(i);
}
}
/**
* 获得父结点的index
* @param index
* @return index
*/
private int getParentsIndex(int index) {
return (index - 1) / 2;
}
private int getLeftIndex(int index) {
return index * 2 + 1;
}
private int getRightIndex(int index) {
return index * 2 + 2;
}
public void insert(int value) {
int[] newHeap = new int[heap.length+1];
newHeap = arrayCopy(newHeap, heap);
newHeap[heap.length] = value;
heap = newHeap;
adjustUpHeap(heap.length-1);
}
/**
* 从下往上调整堆
* @param nodeIndex
*/
private void adjustUpHeap(int nodeIndex) {
int parentsIndex = getParentsIndex(nodeIndex);
if(parentsIndex >= 0 && heap[parentsIndex] < heap[nodeIndex]) {
//子结点大于父结点
swap(parentsIndex, nodeIndex);
adjustUpHeap(parentsIndex); //调整交换后的父结点使得上层成为堆
}
}
/**
* 从上往下调整堆
* @param nodeIndex
*/
private void adjustDownHeap(int nodeIndex) {
int leftIndex = getLeftIndex(nodeIndex);
int rightIndex = getRightIndex(nodeIndex);
//找出根结点、左右子树最大结点
int maxIndex = nodeIndex;
if(leftIndex < heap.length && heap[leftIndex] > heap[maxIndex]) {
maxIndex = leftIndex;
}
if(rightIndex < heap.length && heap[rightIndex] > heap[maxIndex]) {
maxIndex = rightIndex;
}
if(maxIndex != nodeIndex) {
//最大的结点不是父结点
swap(maxIndex, nodeIndex);
adjustDownHeap(maxIndex); //调整交换后的子结点也形成堆
}
}
/**
* 移除堆的根结点
*/
public void removeRootNode() {
//将最后一个结点替换根结点,再将最后的结点移除
swap(0, heap.length-1);
int[] newHeap = new int[heap.length-1];
newHeap = arrayCopy(newHeap, heap);
heap = newHeap;
//调整堆
adjustDownHeap(0);
}
/**
* 交换结点值
* @param maxIndex
* @param nodeIndex
*/
private void swap(int maxIndex, int nodeIndex) {
int temp = heap[maxIndex];
heap[maxIndex] = heap[nodeIndex];
heap[nodeIndex] = temp;
}
/**
* 从一个数组复制数据到另一个数组
* @param newArr
* @param arr
* @return int[]
*/
private int[] arrayCopy(int[] newArr, int[] arr) {
for(int i=0; i<arr.length && i<newArr.length; i++) {
newArr[i] = arr[i];
}
return newArr;
}
public static void main(String[] args) {
int[] data = new int[]{2,7,4,3,5};
MaxHeap maxHeap = new MaxHeap(data);
System.out.println(Arrays.toString(maxHeap.heap));
maxHeap.insert(6);
maxHeap.insert(1);
System.out.println(Arrays.toString(maxHeap.heap));
maxHeap.removeRootNode();
System.out.println(Arrays.toString(maxHeap.heap));
}
}