堆(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的左孩子的索引是 (2i+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
精心整理 | 歷史乾貨文章目錄
【福利】本身蒐集的網上精品課程視頻分享(上)
【數據結構與算法】 通俗易懂講解 二叉樹遍歷
【數據結構與算法】 通俗易懂講解 二叉搜索樹視頻
碼農有道,爲您提供通俗易懂的技術文章,讓技術變的更簡單!blog