二叉堆 是一種完全二叉樹,堆可以分爲最大堆和最小堆。最大堆:父節點的值都大於兩子節點的值;最小堆:父節點的值都小於子節點的值。
圖中就是一個最大堆。
1.那一組數據如何成爲一個最大堆呢
7 | 1 | 3 | 10 | 5 | 2 | 8 | 9 | 6 |
先將它弄成二叉樹看看:
我們先看一下 10這個數字,它比它的子節點都大,但是大於父節點。所以,我們得將 10 與 1 互換,然後 10再和它的父節點比較,10 大於7 ,10和7交換。10 這個樹中最大的數字就到了根節點了。
同時我們會發現:
子節點的座標 = 父節點的座標 * 2 + 1;
子節點的座標 = 父節點的座標 * 2 + 2;
葉子節點的個數 > 整體節點的一半。
因此:要將無序的樹變成最大堆,只需要將每個父節點和它的子節點比較,保證父節點大於自己的子節點。
代碼如下:
private void downJust(int[] arrays, int parentIndex, int length) {
int childIndex = 2 * parentIndex + 1;
int parentNumber = arrays[parentIndex];
while (childIndex <= length) {
if (childIndex + 1 <= length && arrays[childIndex + 1] > arrays[childIndex]) {
childIndex++;
}
if (parentNumber > arrays[childIndex])
break;
arrays[parentIndex] = arrays[childIndex];
parentIndex = childIndex;
childIndex = parentIndex * 2 + 1;
}
arrays[parentIndex] = parentNumber;
}
private void build(int arrays[]) {
for (int i = arrays.length / 2; i >= 0; i--) {
downJust(arrays, i, arrays.length - 1);
}
}
最終的最大堆:
數組:
10 | 7 | 8 | 9 | 5 | 2 | 3 | 1 | 6 |
2. 最大堆建好了,如何堆排序呢?
(1)最大堆的第一個數總是這組數據中,最大的數。
(2)將最後數子和最大數交換,然後,將這個數下沉;
(3)然後將6和自己的子節點下沉,直至比所有子節點都大。
(4)這時候,8就是最大的,再將8和1交換,1做下沉。就這樣,直到數組排好。
代碼如下:
private int[] heapSort(int[] ss) {
int size = ss.length - 1;
build(ss);
while (size > 0) {
ss[0] ^= ss[size];
ss[size] ^= ss[0];
ss[0] ^= ss[size];
downJust(ss, 0, size - 1);
size--;
}
return ss;
}