參考:https://blog.csdn.net/guoweimelon/article/details/50904346
一、堆樹的定義
堆樹的定義如下:
(1)堆樹是一顆完全二叉樹;
(2)堆樹中某個節點的值總是不大於或不小於其孩子節點的值;
(3)堆樹中每個節點的子樹都是堆樹。
當父節點的鍵值總是大於或等於任何一個子節點的鍵值時為最大堆。 當父節點的鍵值總是小於或等於任何一個子節點的鍵值時為最小堆。如下圖所示,左邊為最大堆,右邊為最小堆。
二、堆樹的操作
以最大堆為例進行講解,最小堆同理。
原始數據為a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7},采用順序存儲方式,對應的完全二叉樹如下圖所示:
(1)構造最大堆
在構造堆的基本思想就是:首先將每個葉子節點視為一個堆,再將每個葉子節點與其父節點一起構造成一個包含更多節點的對。
所以,在構造堆的時候,首先需要找到最后一個節點的父節點,從這個節點開始構造最大堆;直到該節點前面所有分支節點都處理完畢,這樣最大堆就構造完畢了。
假設樹的節點個數為n,以1為下標開始編號,直到n結束。對於節點i,其父節點為i/2;左孩子節點為i*2,右孩子節點為i*2+1。最后一個節點的下標為n,其父節點的下標為n/2。
如下圖所示,最后一個節點為7,其父節點為16,從16這個節點開始構造最大堆;構造完畢之后,轉移到下一個父節點2,直到所有父節點都構造完畢。
注意:上面構造最大堆的時候,從底而上,一層一層地不斷基於父節點構造最大堆,直至到達根節點完成整個最大堆的構造;
代碼如下:
//最大堆 //======================================================================= #include <iostream> using namespace std; struct MaxHeap { int *heap; //數據元素的存放空間,下標從1開始存放元素,下標0存放臨時數據 int HeapSize; //數據元素的個數 int MaxSize; //存放數據元素空間的大小 }; //初始化最大堆 void MaxHeapint(MaxHeap &H) { for (int i = H.HeapSize / 2; i > 0; i--) { H.heap[0] = H.heap[i]; int son = i * 2; while (son <= H.HeapSize) { if (son < H.HeapSize && H.heap[son] < H.heap[son + 1]) son++; if (H.heap[son] < H.heap[0]) break; else { H.heap[son / 2] = H.heap[son]; son *= 2; } } H.heap[son / 2] = H.heap[0]; } } //最大堆中插入節點 //思想:先在堆的最后添加一個節點,然后沿着堆樹上升。 void MaxHeapInsert(MaxHeap &H, int x) { if (H.HeapSize == H.MaxSize) return; int i = ++H.HeapSize; while (i != 1 && x > H.heap[i / 2]) { H.heap[i] = H.heap[i / 2]; i = i / 2; } H.heap[i] = x; } //最大堆堆頂節點刪除 //思想:將堆樹的最后的節點提到根結點,然后刪除最大值,然后再把新的根節點放到合適的位置。 void MaxHeapDelete(MaxHeap &H , int &top) { int x; if (H.HeapSize == 0) return; top = H.heap[1]; H.heap[0] = H.heap[H.HeapSize--]; int i = 1, son = i * 2; while (son <= H.HeapSize) { if (son < H.HeapSize && H.heap[son] < H.heap[son + 1]) son++; if (H.heap[0] >= H.heap[son]) break; H.heap[i] = H.heap[son]; i = son; son = son * 2; } H.heap[i] = H.heap[0]; return; } int main(void) { int top; int &top_1 = top; MaxHeap H; cout << "請輸入數據的size: " << endl; cin >> H.HeapSize; H.heap = new int(H.HeapSize + 1); cout << "請按照完全二叉樹輸入數據:" << endl; for (int i = 0; i <= H.HeapSize; i++) { cin >> H.heap[i]; //我們這里默認H.heap[0]為臨時數據,設為0 } MaxHeapint(H); //將二叉樹轉換為最大堆 MaxHeapInsert(H, 3); MaxHeapDelete(H, top); for (int i = 1; i <= H.HeapSize; i++) { cout << H.heap[i] << " "; } cout << endl << top; system("pause"); }