一、最大堆建立
給定N個元素,按照最大堆的要求將元素放入數組中。
兩種做法:
- 通過插入,依次將N個元素插入一個空堆中,復雜度為nlogn。
- 線性復雜度建立堆
- 先將N個元素按照順序存入,先滿足完全二叉樹的特性
- 調整各個節點,讓其滿足最大堆的特性
本文主要介紹第二種方法,線性復雜度創建堆。
二、線性復雜度創建堆
默認創建一個完全二叉樹
從最后一個節點的父節點【第一個父節點】(87)開始調整。87大於9。默認不變,當前子樹是一個堆。
第二個父節點30。最大子節點為72。把72個30繼續互換,當前子樹是一個堆。
第三個父節點83。最大子節點為91。把91和83進行互換,當前子樹也是一個堆。
三次交換后,樹的結構如下。
從43開始調整。87大於43,互換,當前子樹是一個堆。
從66開始調整,91大於66進行互換。83大於66,再次進行互換,當前子樹是一個堆。
最后調整根節點;91和79互換。83和79進行互換,至此。整顆樹都變成了一個堆。
代碼
public static void percDown(HeapStruct heapStruct, int rootIndex) {
Integer[] elements = heapStruct.getElements();
Integer rootValue = elements[rootIndex];
int parentIndex = rootIndex;
while (parentIndex * 2 <= heapStruct.getSize() - 2) {
int childIndex = parentIndex * 2 + 1;
if (childIndex < heapStruct.getSize() - 1 && elements[childIndex].compareTo(elements[childIndex + 1]) < 0) {
childIndex = childIndex + 1;//找到最大的一個兒子
}
if (rootValue.compareTo(elements[childIndex]) > 0) {//當前節點大於最大的兒子節點。
break;
} else {
elements[parentIndex] = elements[childIndex];//和兒子節點進行替換。
parentIndex = childIndex;
}
}
elements[parentIndex]=rootValue;
}
@Test
public void createHeap() {
HeapStruct heapStruct = HeapUtil.initHeap(20);
for (int i = 0; i < 11; i++) {
heapStruct.getElements()[i] = i;//初始化一個數組。
}
for (int n = (heapStruct.getSize() - 1) / 2; n >= 0; n--) {//一個個遍歷父節點,使得當前父節點所在的子樹變成一個堆
HeapUtil.percDown(heapStruct, n);
}
}