在 二叉堆(請戳我) 中介紹了二叉堆的概念以及基本性質,本文主要對二叉堆的主要實現進行分析。首先,仍是給出上文中二叉堆的定義。算法
template <class T> class MaxHeap { private: T *mHeap; // 數據 int mCapacity; // 總的容量 int mSize; // 實際容量 private: // 最大堆的向下調整算法 void filterdown(int start, int end); // 最大堆的向上調整算法(從start開始向上直到0,調整堆) void filterup(int start); public: MaxHeap(); MaxHeap(int capacity); ~MaxHeap(); // 返回data在二叉堆中的索引 int getIndex(T data); // 刪除最大堆中的data int remove(T data); // 將data插入到二叉堆中 int insert(T data); // 打印二叉堆 void print(); };
MaxHeap是最大堆的對應的類。它包括的核心內容是"添加"和"刪除",理解這兩個算法,二叉堆也就基本掌握了。下面對它們進行介紹。數組
假設在最大堆[90,80,70,60,40,30,20,10,50]種添加85,須要執行的步驟以下:
如上圖所示,當向最大堆中添加數據時:先將數據加入到最大堆的末尾,而後儘量把這個元素往上挪,直到挪不動爲止!服務器
將85添加到[90,80,70,60,40,30,20,10,50]中後,最大堆變成了[90,85,70,60,80,30,20,10,50,40]。數據結構
代碼實現以下:ide
/* 最大堆向上調整算法(從start開始向上直到0,調整堆) * 注:數組實現的堆,第N個節點的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。 * 參數說明: start -- 被上調節點的起始位置(通常爲數組中最後一個元素的索引) */ template <class T> void MaxHeap<T>::filterup(int start) { int c = start; // 當前節點(current)的位置 int p = (c-1)/2; // 父(parent)結點的位置 T tmp = mHeap[c]; // 當前節點(current)的大小 while(c > 0) { if(mHeap[p] >= tmp) break; else { mHeap[c] = mHeap[p]; c = p; p = (p-1)/2; } } mHeap[c] = tmp; } /* 將data插入到二叉堆中 * 返回值: 0,表示成功 * -1,表示失敗 */ template <class T> int MaxHeap<T>::insert(T data) { // 若是"堆"已滿,則返回 if(mSize == mCapacity) return -1; mHeap[mSize] = data; // 將"數組"插在表尾 filterup(mSize); // 向上調整堆 mSize++; // 堆的實際容量+1 return 0; }
假設從最大堆[90,85,70,60,80,30,20,10,50,40]中刪除90,須要執行的步驟以下:
如上圖所示,當從最大堆中刪除數據時:先刪除該數據,而後用最大堆中最後一個的元素插入這個空位;接着,把這個「空位」儘可能往上挪,直到剩餘的數據變成一個最大堆。code
從[90,85,70,60,80,30,20,10,50,40]刪除90以後,最大堆變成了[85,80,70,60,40,30,20,10,50]。視頻
注意:考慮從最大堆[90,85,70,60,80,30,20,10,50,40]中刪除60,執行的步驟不能單純的用它的字節點來替換;而必須考慮到"替換後的樹仍然要是最大堆"!
最大堆刪除代碼實現:blog
/* 最大堆的向下調整算法 * 注:數組實現的堆,第N個節點的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。 * 參數說明: * start -- 被下調節點的起始位置 * end -- 截至範圍(通常爲數組中最後一個元素的索引) */ template <class T> void MaxHeap<T>::filterdown(int start, int end) { int c = start; // 當前(current)節點的位置 int l = 2*c + 1; // 左(left)孩子的位置 T tmp = mHeap[c]; // 當前(current)節點的大小 while(l <= end) { // "l"是左孩子,"l+1"是右孩子 if(l < end && mHeap[l] < mHeap[l+1]) l++; // 左右兩孩子中選擇較大者,即mHeap[l+1] if(tmp >= mHeap[l]) break; //調整結束 else { mHeap[c] = mHeap[l]; c = l; l = 2*l + 1; } } mHeap[c] = tmp; } /* 刪除最大堆中的data * 返回值: 0,成功 -1,失敗 */ template <class T> int MaxHeap<T>::remove(T data) { int index; // 若是"堆"已空,則返回-1 if(mSize == 0) return -1; // 獲取data在數組中的索引 index = getIndex(data); if (index==-1) return -1; mHeap[index] = mHeap[--mSize];// 用最後元素填補 filterdown(index, mSize-1);//從index位置自上向下調整爲最大堆 return 0; }
精心整理 | 歷史乾貨文章目錄
【福利】本身蒐集的網上精品課程視頻分享(上)
【數據結構與算法】 通俗易懂講解 二叉樹遍歷
【數據結構與算法】 通俗易懂講解 二叉搜索樹索引
碼農有道,爲您提供通俗易懂的技術文章,讓技術變的更簡單!ci