資料結構 堆

2021-07-03 03:08:30 字數 3116 閱讀 8426

堆排序是最重要的排序演算法之一,在平時的開發以及面試中經常會用到。堆的特點是:

1,有一顆完全二叉樹構成,如圖1;

2,可分為最大堆和最小堆。最大堆的意思就是:任何根節點的資料不小於左右孩子節點的資料;反之,最小堆的意思就是任何節點的資料不大於左右孩子節點的資料;

3,堆排序的演算法複雜度為o(nlgn),比冒泡和插入快,究其原因在於堆只維護區域性最大或最小。

4,堆的儲存用陣列實現,按層儲存,如圖1;

儲存在陣列裡:

圖 1下面分四部分講解堆,分別為:堆的插入,刪除,以及堆排序,最後是堆化的優先佇列。

一,堆的插入

堆的插入只能在最後乙個位置插入,如圖 2。只能在黑色圈的地方插入。插入以後,必須進行更新,以保持堆的性質,即根資料最大或是最小。更新的思路:從插入節點到根節點,依次比較更新,直到滿足條件(本列子就是:根資料小於左右孩子)。

大致原理如**:

關鍵**如下:

注意的是:左孩子和右孩子的順序分別為2i+1,2i+2。結合上面的流程圖,插入的過程為:從下往上依次比較,重新調整堆的結構。

[cpp]view plain

copy

print?

void

minheapfixup(

int* a, 

inti)    

a[i] = temp;    

}    

void

minheapaddnumber(

int* a, 

intn, 

intnnum)    

二,堆的刪除

記住只能刪除最頂部的元素,再把最低端的元素放到最頂端,從上往下依次更新整個堆。示意圖如下:

總結:刪除,只能刪除頭結點,然後從上往下依次調整堆;插入,只能在末端插入,然後從下往上依次調整堆。

三,堆化陣列,採用插入的思想從下往上依次調整堆即可。此時調整每乙個非葉子節點即可。

關鍵**如下:

[cpp]view plain

copy

print?

void

makeminheap(

int* a, 

intn)    

測試:結合圖形中的資料,我們演示一遍:

我們自然要問:維護乙個堆結構的意義何在?

至少有兩個目的:堆排序和優先佇列。

四 ,堆排序。思想:既然我們可以每次取出頂點的資料,取到的資料又是最小資料,根據此思想,我們可以把陣列裡的資料全部取完後得到的資料就是有順序的了。不過跟歸併排序一樣,空間複雜度增加了,必須有乙個陣列去接受。

測試:[cpp]view plain

copy

print?

intb[8];  

for(

inti=0;i<8;++i)  

for(int

i=0;i<8;++i)  

cout

;  

我們知道,任何演算法都得用時間複雜度計算一下,否則,演算法沒什麼意義。由於按樹堆化,樹高lgn,最壞情況下,每層計算n次,所以複雜度為:o(nlgn),跟歸併一樣。

最優佇列:最優佇列是每次都彈出資料的最大或是最小值。每次進佇列後,都要一次更新操作。每次出佇列都要一次刪除操作。

資料結構 堆

最大堆 最小堆 堆的定義是 n個元素的序列,當且僅當滿足如下關係時被成為堆 1 ki k2i 且 ki k2i 1 或 2 ki k2i 且 ki k2i 1 i 1,2,n 2 當滿足 1 時,為最小堆,當滿足 2 時,為最大堆。若將此序列對應的一維陣列堪稱是乙個完全二叉樹,則2i和2i 1個節點...

資料結構 堆

資料結構 堆的操作和實現 當應用優先順序佇列或者進行堆排序時,一般利用堆來實現。堆是乙個完全 除最底層 外都是滿的 二叉樹,並滿足如下條件 1 根結點若有子樹,則子樹一定也是堆。2 根結點一定大於 或小於 子結點。因為要求堆必須是完全二叉樹,所以可以用線性的資料結構,比如陣列,來實現堆。利用陣列實現...

資料結構 堆

堆常用來實現優先佇列,在這種佇列中,待刪除的元素為優先順序最高 最低 的那個。在任何時候,任意優先元素都是可以插入到佇列中去的,是電腦科學中一類特殊的資料結構的統稱 最大 最小 堆是一棵每乙個節點的鍵值都不小於 大於 其孩子 如果存在 的鍵值的樹。大頂堆是一棵完全二叉樹,同時也是一棵最大樹。小頂堆是...