【數據結構與算法】 通俗易懂講解 二叉堆實現

在 二叉堆(請戳我) 中介紹了二叉堆的概念以及基本性質,本文主要對二叉堆的主要實現進行分析。首先,仍是給出上文中二叉堆的定義。算法

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;
}

推薦閱讀:

精心整理 | 歷史乾貨文章目錄
【福利】本身蒐集的網上精品課程視頻分享(上)
【數據結構與算法】 通俗易懂講解 二叉樹遍歷
【數據結構與算法】 通俗易懂講解 二叉搜索樹索引

專一服務器後臺技術棧知識總結分享

歡迎關注交流共同進步

【數據結構與算法】 通俗易懂講解 二叉堆實現

碼農有道 coding

碼農有道,爲您提供通俗易懂的技術文章,讓技術變的更簡單!ci

相關文章
相關標籤/搜索