1. 程式人生 > >最大最小堆整理 & heapq最小最大堆

最大最小堆整理 & heapq最小最大堆

參考資料:
關於堆排序的演算法參考:https://www.cnblogs.com/chengxiao/p/6129630.html
關於堆排序的視訊演示:
https://www.bilibili.com/video/av18980178/
對於一個數組,可以使用min()和max()來求最大最小值而不是使用堆,但是根據python的wiki:https://wiki.python.org/moin/TimeComplexity
可以看到min()和max()的時間複雜度為O(N).
在這裡插入圖片描述
使用最大最小堆的好處:堆排序的插入時間複雜度為O(logN),得到最大最小值的時間複雜度為O(1)


python實現堆排序

參考:https://www.jianshu.com/p/e003872fa7b9

建立堆

建立堆有兩種方式,heappush()和heapify()。
匯入heapq庫(python自帶庫)

import heapq
data = [1,5,3,2,8,5]
heap = []
for n in data:
    heapq.heappush(heap, n)
print(heap)
>>>> [1, 2, 3, 5, 8, 5]

或者

import heapq
data = [1,5,3,2,8,5]
heapq.heapify(data)
>>
>> [1, 2, 3, 5, 8, 5]

可以看到兩種堆是一樣的,如果資料存在記憶體中,是不是使用heapify好一點

訪問堆內容

最小堆使用data[0]即可訪問最小元素

import heapq
data = [1,5,3,2,8,5]
heapq.heapify(data)
print(data)
print(data[0])
>>>> 
[1, 2, 3, 5, 8, 5]
1

使用heappop刪除堆最小的元素

import heapq

data = [1,5,3,2,8,5]
heapq.heapify(data)
print(heapq.heappop(data)) print(data) >>>> 1 [2, 5, 3, 5, 8]

可以看到刪除了最小元素,調整之後仍然是最小堆,就是與根節點與葉子節點互換之後,刪除葉子節點,繼續調整位置。


刪除最小元素,替換新的值heapreplace()

import heapq

data = [1,5,3,2,8,5]
heapq.heapify(data)
heapq.heapreplace(data, 10)
print(data)
>>>>
[2, 5, 3, 10, 8, 5]

若干個最大最小值

heapq還包括兩個檢查可迭代物件的函式,查詢其中包含的最大值與最小值的範圍

import heapq

data = [1,5,3,2,8,5]
print heapq.nlargest(3, data)
print heapq.nsmallest(3, data)
>>>>
[8, 5, 5]
[1, 2, 3]

heapq最大堆

heapq支援最大堆

import heapq

data = [1,5,3,2,8,5]
heapq._heapify_max(data)
print(data)
print(heapq._heappop_max(data))
print(data)
heapq._heapreplace_max(data, 12)
print(data)
>>>>
[8, 5, 5, 2, 1, 3]
8
[5, 5, 3, 2, 1]
[12, 5, 3, 2, 1]

可以看到,支援最大堆,但是有一個問題,如下面程式碼

import heapq

data = [1,5,3,2,8,5]
heapq._heapify_max(data)
print(data)
print(heapq._heappop_max(data))
print(data)
heapq._heapreplace_max(data, 12)
print(data)
heapq.heappush(data, 15)
print(data)
>>>>

[8, 5, 5, 2, 1, 3]
8
[5, 5, 3, 2, 1]
[12, 5, 3, 2, 1]
[12, 5, 3, 2, 1, 15]
12

可以看到,往heapq不支援maxpush,也就是說往裡面push一個15,得到的堆並不是最大堆,在Stack Overflow上面有解答https://stackoverflow.com/questions/2501457/what-do-i-use-for-a-max-heap-implementation-in-python

The easiest way is to invert the value of the keys and use heapq. For example, turn 1000.0 into -1000.0 and 5.0 into -5.0.

也就是將負數轉化為整數插入到最小堆,每次輸入輸出的時候都取相反數,但是當負數和正數同時存在的時候,就會有問題。
當然也可用再使用O(logN)來創造最大堆
反正也需要O(logN)的時間複雜度

heapq._heapify_max(data)