1. 程式人生 > >最大堆和最小堆

最大堆和最小堆

new clas 代碼 轉移 break OS 分支 -s std

參考: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"); }

最大堆和最小堆