堆的基本概念及常用操作

2021-08-15 15:58:51 字數 4540 閱讀 2606

二叉堆滿足二個特性:

1.父結點的鍵值總是大於或等於(小於或等於)任何乙個子節點的鍵值

2.每個結點的左子樹和右子樹都是乙個二叉堆(都是最大堆或最小堆

當父結點的鍵值總是大於或等於任何乙個子節點的鍵值時為最大堆。當父結點的鍵值總是小於或等於任何乙個子節點的鍵值時為最小堆

堆的主要操作是插入刪除最小(最大)元素(元素值本身為優先順序鍵值,小元素享有高優先順序)。在插入或者刪除操作之後,我們必須保持該實現應有的性質: 1.完全二叉樹2.每個節點值都小於或等於它的子節點

以下的所有操作都以以最小堆為例,最大堆是同樣的道理。

1. 堆的儲存

一般都用陣列來表示堆,

i i

結點的父結點下標就為(i

–1)/

2' role="presentation" style="position: relative;">(i–

1)/2

(i–1

)/2。它的左右子結點下標分別為2∗

i+1 2∗i

+1和2∗i+

2 2∗i

+2。如第0個結點左右子結點下標分別為1和2。

2. 插入

在插入操作的時候,將新插入的節點放在完全二叉樹最後的位置,再和父節點比較。如果new節點比父節點小,那麼交換兩者。交換之後,繼續和新的父節點比較…… 直到new節點不比父節點小,或者new節點成為根節點。這樣得到的樹,就恢復了堆的性質。

# 列印的結果是

[1, 2, 3, 4, 5, 6, 4]

這個在python中已有自帶的官方庫heapq實現

from heapq import *

x = [9,7,6,4,3,1]

# build heap

heapify(x)

print(x)

# insert

print(x)

'''列印結果如下'''

# 原始堆

[1, 3, 6, 4, 7, 9]

# 插入2之後的結果

[1, 3, 2, 4, 7, 9, 6]

3. 刪除

刪除操作只能刪除根節點。根節點刪除後,我們會有兩個子樹,我們需要基於它們重構堆。 讓最後乙個節點last成為新的節點,從而構成乙個新的二叉樹。再將last節點不斷的和子節點比較。如果last節點比兩個子節點中小的那乙個大,則和該子節點交換。直到last節點不大於任一子節點都小,或者last節點成為葉節點。

# 列印的結果是

[2, 4, 6, 7, 8, 13]

用heapq實現是

x = [1, 3, 2, 4, 7, 9, 6]

# delete

print(min_value)

print(x)

'''列印的結果是'''

1# 彈出的最小元素

[2, 3, 6, 4, 7, 9] # 刪除後的結果

4. 堆化陣列(建堆)

有了堆的插入和刪除後,再考慮下如何對乙個資料進行堆化操作。

# build minheap

defmakeminheap

(a):

n = len(a)

for i in range(n/2-1, -1, -1):

minheapfixdown(a, i)

if __name__ == '__main__':

c = [9,5,3,1,6,7,3,10,8]

makeminheap(c)

print(c)

# 列印的結果是

[1, 5, 3, 8, 6, 7, 3, 10, 9]

heapq直接使用heapify建堆

from heapq import *

x = [9,7,6,4,3,1]

# build heap

heapify(x)

'''列印的結果'''

[1, 3, 6, 4, 7, 9] # 建好的堆

建堆的時間複雜度:o(

n)o (n

)首先可以看到堆建好之後堆中第0個資料是堆中最小的資料。取出這個資料再執行下堆的刪除操作。這樣堆中第0個資料又是堆中最小的資料,重複上述步驟直至堆中只有乙個資料時就直接取出這個資料。

# heap sort

defheapsort

(nums):

ans =

# 建堆

makeminheap(nums)

while len(nums) > 1:

minheapdeletenumber(nums)

return ans

if __name__ == '__main__':

nums = [1,4,2,5,6,8,4]

print(heapsort(nums))

# 列印的結果是

[1, 2, 4, 4, 5, 6, 8]

nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]

heapify(nums)

res =

while nums:

print res

'''列印的結果是'''

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

複雜度分析:

堆排序的時間複雜度:由於每次重新恢復堆的時間複雜度為o(

logn

) o(l

ogn)

,共n−

1 n−1

次重新恢復堆操作,再加上前面建立堆時間複雜度o(

n)o (n

)。二次操作時間相加還是o(

nlog

n)o (n

logn

)

Linux 基本概念及操作

建立檔名 進入目錄 終止當前程式 ctrl d鍵盤輸入結束或退出終端 ctrl s暫停當前程式,暫停後按下任意鍵恢復執行 ctrl z將當前程式放到後台執行,恢復到前台為命令fg ctrl a將游標移至輸入行頭,相當於home鍵 ctrl e將游標移至輸入行末,相當於end鍵 ctrl k刪除從游標...

Linux基本概念及操作

進入乙個目錄,cd是乙個命令 檢視當前所在目錄 其他快捷鍵 按鍵作用 ctrl d 鍵盤輸入結束或退出終端 ctrl s 暫停當前程式,暫停後按下任意鍵恢復執行 ctrl z 將當前程式放到後台執行,恢復到前台為命令fg ctrl a 將游標移至輸入行頭,相當於home鍵 ctrl e 將游標移至輸...

Linux基本概念及操作

1.0linux歷史 1.1基礎操作 linux登陸有兩種,一種是xwindows登陸,另一種是shell登陸。前一種登陸方式通常是用vnc,後一種通常是telnet ssh vnc 通過視窗登陸 常用基本命令 1.2 linux 檔案 在linux中所有東西都稱之為檔案,可以通過檔案許可權的第乙個...