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

堆的應用場景

堆(heap)又被爲優先隊列(priority queue)。儘管名爲優先隊列,但堆並非隊列。回憶一下,在隊列中,咱們能夠進行的限定操做是dequeue和enqueue。dequeue是按照進入隊列的前後順序來取出元素。而在堆中,咱們不是按照元素進入隊列的前後順序取出元素的,而是按照元素的優先級取出元素。算法

這就好像候機的時候,不管誰先到達候機廳,老是頭等艙的乘客先登機,而後是商務艙的乘客,最後是經濟艙的乘客。每一個乘客都有頭等艙、商務艙、經濟艙三種個鍵值(key)中的一個。頭等艙->商務艙->經濟艙依次享有從高到低的優先級。數組

再好比,封建社會的等級制度,也是一個堆。在這個堆中,國王、貴族、騎士和農民是從高到低的優先級。
【數據結構與算法】 通俗易懂講解 二叉堆
Linux內核中的調度器(scheduler)會按照各個進程的優先級來安排CPU執行哪個進程。計算機中一般有多個進程,每一個進程有不一樣的優先級(該優先級的計算會綜合多個因素)。內核會找到優先級最高的進程,並執行。若是有優先級更高的進程被提交,那麼調度器會轉而安排該進程運行。優先級比較低的進程則會等待。「堆」是實現調度器的理想數據結構。
堆的一個經典的實現是徹底二叉樹(complete binary tree)。這樣實現的堆成爲二叉堆(binary heap)。服務器

二叉堆介紹-

前面講了二叉堆是徹底二元樹或者是近似徹底二元樹實現的堆結構,關於二叉樹,詳細介紹請見前面文章二叉搜索樹(請戳我),二叉堆按照數據的排列方式能夠分爲兩種:最大堆和最小堆。
最大堆:父結點的鍵值老是大於或等於任何一個子節點的鍵值;以下圖左
最小堆:父結點的鍵值老是小於或等於任何一個子節點的鍵值。以下圖右
【數據結構與算法】 通俗易懂講解 二叉堆數據結構

二叉堆定義及性質

二叉堆通常都經過"數組"來實現。數組實現的二叉堆,父節點和子節點的位置存在必定的關係。有時候,咱們將"二叉堆的第一個元素"放在數組索引0的位置,有時候放在1的位置。固然,它們的本質同樣(都是二叉堆),只是實現上稍微有一丁點區別。注意:本文二叉堆的實現通通都是採用"二叉堆第一個元素在數組索引爲0"的方式!
假設"第一個元素"在數組中的索引爲 0 ,對於父節點和子節點的位置有以下關係:
(1) 索引爲i的左孩子的索引是 (2i+1);
(2) 索引爲i的左孩子的索引是 (2
i+2);
(3) 索引爲i的父結點的索引是 floor((i-1)/2);
【數據結構與算法】 通俗易懂講解 二叉堆
下面給出二叉堆的C++定義,爲了通用性,定義成一個類模板:MaxHeapide

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是最大堆的對應的類。它包括的核心內容是"添加"和"刪除",理解這兩個算法,二叉堆也就基本掌握了。下篇文章對它們進行介紹。code

推薦閱讀:

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

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

歡迎關注交流共同進步

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

碼農有道 coding

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

相關文章
相關標籤/搜索