Python 模块之heapq
1、heapq介紹:
1)堆是非線性的樹形的數據結構,有兩種堆,最大堆與最小堆。(?heapq庫中的堆默認是最小堆)
- 最大堆,樹種各個父節點的值總是大于或等于任何一個子節點的值。
- 最小堆,樹種各個父節點的值總是小于或等于任何一個子節點的值。
2)堆是一個二叉樹,其中最小堆每個父節點的值都小于或等于其所有子節點的值。整個最小堆的最小元素總是位于二叉樹的根節點。
3)堆是用數組實現的二叉樹,所以它沒有使用父指針或者子指針。堆根據“堆屬性”來排序,“堆屬性”決定了樹中節點的位置。
4)python的heapq模塊提供了對堆的支持。 heapq堆數據結構最重要的特征是heap[0]永遠是最小的元素
更多知識參考:數據結構:堆(Heap)
2、堆屬性
1)例子:
這是一個最大堆,,因為每一個父節點的值都比其子節點要大。10?比?7?和?2?都大。7?比?5?和?1都大。
根據這一屬性,那么最大堆總是將其中的最大值存放在樹的根節點。而對于最小堆,根節點中的元素總是樹中的最小值。堆屬性非常有用,因為堆常常被當做優先隊列使用,因為可以快速地訪問到“最重要”的元素。
注意:堆的根節點中存放的是最大或者最小元素,但是其他節點的排序順序是未知的。例如,在一個最大堆中,最大的那一個元素總是位于 index 0 的位置,但是最小的元素則未必是最后一個元素。--唯一能夠保證的是最小的元素是一個葉節點,但是不確定是哪一個。
3、來自數組的樹
用數組來實現樹相關的數據結構也許看起來有點古怪,但是它在時間和空間上都是很高效的。
我們準備將上面例子中的樹這樣存儲:
[ 10, 7, 2, 5, 1 ]就這么多!我們除了一個簡單的數組以外,不需要任何額外的空間。
如果我們不允許使用指針,那么我們怎么知道哪一個節點是父節點,哪一個節點是它的子節點呢?問得好!節點在數組中的位置index 和它的父節點以及子節點的索引之間有一個映射關系。
如果?i?是節點的索引,那么下面的公式就給出了它的父節點和子節點在數組中的位置:
parent(i) = floor((i - 1)/2)left(i) = 2i + 1right(i) = 2i + 2注意?right(i)?就是簡單的?left(i) + 1。左右節點總是處于相鄰的位置。
我們將寫公式放到前面的例子中驗證一下。
| 10 | 0 | -1 | 1 | 2 |
| 7 | 1 | 0 | 3 | 4 |
| 2 | 2 | 0 | 5 | 6 |
| 5 | 3 | 1 | 7 | 8 |
| 1 | 4 | 1 | 9 | 10 |
注意:根節點(10)沒有父節點,因為?-1?不是一個有效的數組索引。同樣,節點?(2),(5)和(1)?沒有子節點,因為這些索引已經超過了數組的大小,所以我們在使用這些索引值的時候需要保證是有效的索引值。
注意這個方案與一些限制。你可以在普通二叉樹中按照下面的方式組織數據,但是在堆中不可以:
在堆中,在當前層級所有的節點都已經填滿之前不允許開是下一層的填充,所以堆總是有這樣的形狀:
4、heapq方法介紹:
1)heappush(heap, item)
heapq.heappush(heap, item) 將item壓入到堆數組heap中。如果不進行此步操作,后面的heappop()失效,會直接返回原列表第一個值,而且必須從頭開始heappush,不然也會返回原列表第一個值。 例: a = [12,2,4,5,63,3,2] heapq.heappush(a,123) >>>[12, 2, 4, 5, 63, 3, 2, 123] b = heapq.heappop(a) >>>122)heappop(heap)
刪除并返回最小值,因為堆的特征是heap[0]永遠是最小的元素,所以一般都是刪除第一個元素。 注意,如果不是壓入堆中,而是通過append追加一個數值,堆的函數并不能操作這個增加的數值,或者說它堆對來講是不存在的。 例: a = [] heapq.heappush(a,11) heapq.heappush(a,2) heapq.heappush(a,3) heapq.heappush(a,4)a.append(1) b = heapq.heappop(a) >>b=23)heapq.heapify(list)
參數必須是list,此函數將list變成堆,實時操作。從而能夠在任何情況下使用堆的函數 例: a = [12,2,4,5,63,3,2] heapq.heapify(a) heapq.heappop(a)4)heapq.heappushpop(heap, item)
是上述heappush和heappop的合體,同時完成兩者的功能,注意:相當于先操作了heappush(heap,item),然后操作heappop(heap)5)heapq.heapreplace(heap, item)
是上述heappop和heappush的聯合操作。注意:與heappushpop(heap,item)的區別在于,順序不同,這里是先進行刪除,后壓入堆6)heapq.merge(*iterables)
將多個堆合并 a = [2, 4, 6] b = [1, 3, 5] c = heapq.merge(a, b) >>[1, 2, 3, 4, 5, 6]7)heapq.nlargest(n, iterable,[ key])
查詢堆中的最大n個元素8)heapq.nsmallest(n, iterable,[ key])
查詢堆中的最小n個元素9)創建最大堆
heapq._heapify_max(queue)5、注意事項
當建堆的參數list的元素為tuple時,以tuple的第0個元素排序
例1:
S = "aab" counts = collections.Counter(S).items() heap = list(counts) heapq._heapify_max(heap) print(heap)輸出結果為:
[('b', 1), ('a', 2)]
# 按字母的字典序進行排序
例2:
S = "aab" counts = collections.Counter(S).items() heap = [(x[1], x[0]) for x in counts] heapq._heapify_max(heap) print(heap)?
[(2, 'a'), (1, 'b')]
# 按字母的出現順序排序
參考文章:
數據結構:堆(Heap)
Python 模塊之heapq
總結
以上是生活随笔為你收集整理的Python 模块之heapq的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python中collections模块
- 下一篇: Python中单个下划线“_”变量的目的