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