最小堆,是一種經過排序的完全二叉樹,其中任一非終端節點的數據值均不大於其左子節點和右子節點的值。
通俗的說就是:
1.數組來實現二叉樹,所以滿足二叉樹的特性。
2.根元素是最小的元素,父節點小於它的兩個子節點。
3.樹中的元素是相對有序的。
如何實現堆的相對有序是關鍵。
插入元素時,插入到數組中的最後一個元素的後面,然後與該節點的父節點比較大小。如果插入的元素小於父節點元素,那麼與父節點交換位置。然後插入元素交換到父節點位置時,又與該節點的父節點比較,直到大於父節點元素或者到達堆頂。該過程叫做上浮,即插入時上浮。
移除元素時,只能從堆頂移除元素,再取最後一個元素放到堆頂中。然後堆頂節點與子節點比較時,先取子節點中的較小者,如果堆頂節點大於較小子節點,那麼交換位置。此時堆頂節點元素交換到較小子節點上。然後再與其較小子節點比較,直到小於較小子節點或者到達葉子節點爲止。該過程叫做下沉,即移除元素時下沉。
附上一個簡單的最小堆插入代碼:
#include <stdio.h>
#define MAXN 1005
#define MINDATA -10005
int Data[MAXN], size;
void Insert(int x) {
int i = ++size;
for( ; x < Data[i/2]; i /= 2)
Data[i] = Data[i/2];
Data[i] = x;
}
int main() {
int N, M;
int x;
scanf("%d%d", &N, &M);
Data[0] = MINDATA;
size = 0;
while(N--) {
scanf("%d", &x);
Insert(x);
}
while(M--) {
scanf("%d", &x);
printf("%d", Data[x]);//指定節點到根節點的路徑遍歷
x /= 2;
while(x) {
printf(" %d", Data[x]);
x /= 2;
}
printf("\n");
}
return 0;
}