例說資料結構&STL(六)——heap
1 白話佇列(queue)
heap並不歸屬於STL容器元件,不像佇列queue它們擁有自己獨立的類定義,它只能藉助其他諸如陣列,vector等資料結構完成堆的構造操作。但是heap實際當中有很重要的應用,像大家最熟悉的堆排序,所以STL中還是有對應的函式定義的。
接觸過堆排序的知道,所謂binary heap 就是一種complete binary tree(完全二叉樹),也就是說,整棵binary tree 除了最底層的葉節點之外,是填滿的,而最底層的葉節點(s)由左至右又不得有空隙。如下圖所示:
將像上圖一樣,我們還是藉助例如陣列儲存完全二叉樹的資訊,當完全二叉樹中的某個節點位於陣列的i處時,其左子節點必位於陣列的2i處,其右子節點比位於陣列的2i+1處,其父節點必位於“i/2”處。通過這麼簡單的位置規則,陣列可以輕易實現出完全二叉樹。
根據元素的排列方式,heap可分為最大堆(max-heap )和 最小堆(min-heap)兩種,前者每個節點的鍵值都大於或等於其子節點鍵值,後者的每個節點鍵值都小於或等於其子節點鍵值。STL預設提供的是最大堆。
2 STL中heap實戰
2.1 包含heap的標頭檔案
heap構建,排序,刪除元素等函式操作是定義在algorithm標頭檔案中的,其實這個標頭檔案中還包含STL很多其他非常優秀的演算法,感興趣的可以查閱相關資料自行學習,它可以讓你的程式設計事半功倍。另外一直強調的std名稱空間,實現如下:
#include<algorithm>
using namespace std;
2.2 構建堆
前面說過堆的構建需要藉助一個載體,本文中我們圍繞vector容器來搭建與處理堆。首先我們來看看堆的構建:
int nArr[10] = {0,2,8,9,1,4,3,7,5,6};
vector<int> vec(nArr,nArr+10); //構建載體vector
make_heap(vec.begin(),vec.end()); //圍繞vec構建一個堆。
上面vector初始化的時候儲存資料順序是0,2,8,9,1,4,3,7,5,6,經過堆構建處理最後vector中資料的順序變成9,7,8,5,6,4,3,2,0,1。新的vector中的資料是完全符合堆的規則的,即前者每個節點的鍵值都大於或等於其子節點鍵值,後者的每個節點鍵值都小於或等於其子節點鍵值。
2.3 出堆操作
此處出堆操作就是指刪除堆中根節點。下圖是 pop_heap演算法的實際操演情況。既然身為max-heap,最大值必然在根節點。pop操作取走根節點(其實是設至底部容器vector的尾端節點)後,為了滿足完全二叉樹的條件,必須割捨最下層最右邊的葉節點,並將其值重新安插至max-heap(因此有必要重新調整heap結構)。
這裡需要注意的是對vector出堆操作必須保證vector中資料是堆儲存的,也就是出堆之前一定要make_heap()操作。此外出堆之後,並不是vector中最大值被刪除,而是暫且儲存到vector中最後一位,也就是說真正刪除該數還必須在vector中刪除依次。程式如下:
pop_heap(vec.begin(),vec.end()); // 出堆根節點,將其暫存vector最後一位
vec.pop_back(); // vector刪除出堆的資料,即最後一位,現在是8,7,4,5,6,1,3,2,0
2.4 入堆操作
和出堆正好相反,入堆是先將數放置在堆葉節點,並且是由左向右第一個空葉節點,時刻保證是完全二叉樹的原則,然後依次上溯。上溯就是將新節點拿來與其父節點比較,如果其鍵值(key)比父節點大,就父子對換位置。如此一直上溯,直到不需對換或直到根節點為止。過程如下:
需要注意在入堆之前,一定要保證vector尾部已經插入一個新的數,而且和出堆一樣,操作之前一定要保證vector已經建堆。程式如下:
vec.push_back(50); // 先新增一個新資料
push_heap(vec.begin(),vec.end()); //再入堆操作
2.5 堆排序操作
堆排序操作的前提也是一樣,需要構建堆,然後我們就可以進行堆排序讓vector中的數是順序排列的,通過上面的操作最後的順序就是0,1,2,3,4,5,6,7,8,50。記住是增序。
sort_heap(vec.begin(),vec.end()); //堆排序
這塊解釋一下為什麼是增序,實際上上面的排序實現就是依靠依次出堆的操作完成的,我們已經知道出堆都會將預設大根節點儲存在vector的末尾,所以最終所有的資料就依次在vector中是增序排列的。
3 小結
上面詳細的介紹了heap資料結構以及STL中提供的幾個與堆有關的方法介面。由於heap的所有元素都必須遵循完全二叉樹的排列規則,所以heap不提供遍歷功能,也不提供迭代器。
以上是個人學習記錄,由於能力和時間有限,如果有錯誤望讀者糾正,謝謝!
轉載請註明出處:http://blog.csdn.net/FX677588/article/details/76358777
相關文章
- 例說資料結構&STL(十三)——pair資料結構AI
- 例說資料結構&STL(一)——vector資料結構
- 例說資料結構&STL(二)——list資料結構
- 例說資料結構&STL(三)——deque資料結構
- 例說資料結構&STL(四)——queue資料結構
- 例說資料結構&STL(五)——stack資料結構
- 例說資料結構&STL(八)——set資料結構
- 例說資料結構&STL(九)——map資料結構
- 例說資料結構&STL(十二)——iterator資料結構
- 例說資料結構&STL(七)——priority_queue資料結構
- 例說資料結構&STL(十)——hash_set/unordered_set資料結構
- 例說資料結構&STL(十一)——hash_map/unordered_map資料結構
- 資料結構 - 堆(Heap)資料結構
- 資料結構之堆(Heap)資料結構
- STL中經常使用資料結構資料結構
- 《STL原始碼剖析》-- stl_heap.h原始碼
- 資料結構&堆&heap&priority_queue&實現資料結構
- 『嗨威說』資料結構 - 第六章學習內容小結資料結構
- 面試集錦(六)資料結構(2)面試資料結構
- 面試集錦(六)資料結構(1)面試資料結構
- 《大話資料結構》讀後總結(六)資料結構
- 傳說中的資料結構_JAVA資料結構Java
- 資料結構 第一節 第六課資料結構
- 資料結構:線性表-例題資料結構
- 【PG結構】Postgresql資料庫資料目錄說明SQL資料庫
- 資料結構和演算法(六)佇列資料結構演算法佇列
- java資料結構基礎-利用Heap(堆)實現PriorityQueue(優先佇列)Java資料結構佇列
- 從一條資料說起——InnoDB儲存資料結構資料結構
- 關於架構離不開資料結構之說架構資料結構
- 說說你對資料結構的理解?有哪些?區別?資料結構
- 【資料結構】第六章學習小結--- 圖資料結構
- ECshop 每個資料庫表結構說明資料庫
- PostgreSQL儲存引擎之heap tuple結構SQL儲存引擎
- 資料結構實驗之連結串列六:有序連結串列的建立資料結構
- 結構化資料、半結構化資料和非結構化資料
- 學習javascript資料結構與演算法(六)——圖JavaScript資料結構演算法
- 第六部分函式、資料結構函式資料結構
- 深入剖析Redis系列(六) - Redis資料結構之雜湊Redis資料結構