python 堆和優(yōu)先隊(duì)列的使用詳解
1.heapq
python里面的堆是通過(guò)在列表中維護(hù)堆的性質(zhì)實(shí)現(xiàn)的。這一點(diǎn)與C++中heap一系列的算法類(lèi)似,底層是通過(guò)堆vector的維護(hù)獲取堆的性質(zhì)。
關(guān)于二叉樹(shù)
二叉樹(shù)的特點(diǎn):
二叉樹(shù)是一種存儲(chǔ)數(shù)據(jù)元素的匯集數(shù)據(jù)結(jié)構(gòu)。
二叉樹(shù)最重要的性質(zhì)就是樹(shù)的高度和樹(shù)中可以容納的最大結(jié)點(diǎn)個(gè)數(shù)之間的關(guān)系。樹(shù)的高度類(lèi)似于表長(zhǎng),是從根結(jié)點(diǎn)到其他結(jié)點(diǎn)的最大距離。在長(zhǎng)為n的表里只能容納n個(gè)結(jié)點(diǎn),而在高為h的二叉樹(shù)中則可以容納大約2^h個(gè)結(jié)點(diǎn),這是表和樹(shù)的最大不同點(diǎn)。
一般的元素插入,如果是按線性順序排列的,那么操作必然需要O(n)的時(shí)間(需要對(duì)n個(gè)數(shù)據(jù)進(jìn)行移位處理),要突破這個(gè)限制,必須考慮其他數(shù)據(jù)結(jié)構(gòu)的組織方式。二叉樹(shù)就是一種高效插入的存儲(chǔ)方式。
堆排序利用的是完全二叉樹(shù)。
python堆的部分API,其他API查閱文檔python_heap_API和 heapq的源代碼
import heapq #向堆中插入元素,heapq會(huì)維護(hù)列表heap中的元素保持堆的性質(zhì) heapq.heappush(heap, item) #heapq把列表x轉(zhuǎn)換成堆 heapq.heapify(x) #從可迭代的迭代器中返回最大的n個(gè)數(shù),可以指定比較的key heapq.nlargest(n, iterable[, key]) #從可迭代的迭代器中返回最小的n個(gè)數(shù),可以指定比較的key heapq.nsmallest(n, iterable[, key]) #從堆中刪除元素,返回值是堆中最小或者最大的元素 heapq.heappop(heap)
1.1.內(nèi)置類(lèi)型
從上述源代碼可以看出來(lái),heapq使用的內(nèi)置的小于號(hào),或者類(lèi)的__lt__比較運(yùn)算來(lái)進(jìn)行比較。
def heapq_int(): heap = [] #以堆的形式插入堆 heapq.heappush(heap,10) heapq.heappush(heap,1) heapq.heappush(heap,10/2) [heapq.heappush(heap,i) for i in range(10)] [heapq.heappush(heap,10 - i) for i in range(10)] #最大的10個(gè)元素 print heapq.nlargest(10,heap) #輸出所有元素 print [heapq.heappop(heap) for i in range(len(heap))]
1.2.元組類(lèi)型
元素會(huì)默認(rèn)調(diào)用內(nèi)置比較函數(shù)cmp
def heapq_tuple():
heap = []
#向推中插入元組
heapq.heappush(heap,(10,'ten'))
heapq.heappush(heap,(1,'one'))
heapq.heappush(heap,(10/2,'five'))
while heap:
print heapq.heappop(heap),
print
1.2.類(lèi)類(lèi)型
類(lèi)類(lèi)型,使用的是小于號(hào)_lt_,當(dāng)然沒(méi)有重寫(xiě)但是有其他的比較函數(shù)例如:_le_,_gt_,_cmp_,也是會(huì)調(diào)用的,和小于號(hào)等價(jià)的都可以調(diào)用(測(cè)試了gt),具體的這些操作之間的關(guān)系我也沒(méi)有研究過(guò)。如果類(lèi)里面沒(méi)有重寫(xiě)_lt_,會(huì)調(diào)用其他的比較操作符,從源代碼可以看出來(lái),如果沒(méi)有_lt_,那么會(huì)調(diào)用_ge_函數(shù)。
所以可以重寫(xiě)上述的那些函數(shù):
class Skill(object):
def __init__(self,priority,description):
self.priority = priority
self.description = description
def __lt__(self,other):#operator <
return self.priority < other.priority
def __ge__(self,other):#oprator >=
return self.priority >= other.priority
def __le__(self,other):#oprator <=
return self.priority <= other.priority
def __cmp__(self,other):
#call global(builtin) function cmp for int
return cmp(self.priority,other.priority)
def __str__(self):
return '(' + str(self.priority)+',\'' + self.description + '\')'
def heapq_class():
heap = []
heapq.heappush(heap,Skill(5,'proficient'))
heapq.heappush(heap,Skill(10,'expert'))
heapq.heappush(heap,Skill(1,'novice'))
while heap:
print heapq.heappop(heap),
print
所以如果要用到自己定義的類(lèi)型,可以重寫(xiě)上述函數(shù),就可以使用heapq函數(shù)了。
2.PriorityQueue
PriorityQueue的python源代碼PriorityQueue
從源代碼可以看出來(lái),PriorityQueue使用的就是heapq來(lái)實(shí)現(xiàn)的,所以可以認(rèn)為兩者算法本質(zhì)上是一樣的。當(dāng)然PriorityQueue考慮到了線程安全的問(wèn)題。
下面給出PriorityQueue的部分API和使用方法。
參考Queue
#向隊(duì)列中添加元素 Queue.put(item[, block[, timeout]]) #從隊(duì)列中獲取元素 Queue.get([block[, timeout]]) #隊(duì)列判空 Queue.empty() #隊(duì)列大小 Queue.qsize()
2.1.內(nèi)置類(lèi)型
直接調(diào)用內(nèi)置函數(shù)cmp進(jìn)行比較
try:
import Queue as Q #python version < 3.0
except ImportError:
import queue as Q #python3.*
def PriorityQueue_int():
que = Q.PriorityQueue()
que.put(10)
que.put(1)
que.put(5)
while not que.empty():
print que.get(),
print
2.2.元組類(lèi)型
def PriorityQueue_tuple():
que = Q.PriorityQueue()
que.put((10,'ten'))
que.put((1,'one'))
que.put((10/2,'five'))
while not que.empty():
print que.get(),
print
2.2.自定義類(lèi)型
class Skill(object):
def __init__(self,priority,description):
self.priority = priority
self.description = description
#下面兩個(gè)方法重寫(xiě)一個(gè)就可以了
def __lt__(self,other):#operator <
return self.priority < other.priority
def __cmp__(self,other):
#call global(builtin) function cmp for int
return cmp(self.priority,other.priority)
def __str__(self):
return '(' + str(self.priority)+',\'' + self.description + '\')'
def PriorityQueue_class():
que = Q.PriorityQueue()
skill5 = Skill(5,'proficient')
skill6 = Skill(6,'proficient6')
que.put(skill6)
que.put(Skill(5,'proficient'))
que.put(Skill(10,'expert'))
que.put(Skill(1,'novice'))
while not que.empty():
print que.get(),
print
其他的一些方法的使用還是需要參考給出的文檔的。
最后一點(diǎn),讓我比較奇怪的是(可能我并沒(méi)有找到),沒(méi)有提供像排序函數(shù)那樣,指定比較方法函數(shù),這點(diǎn)和c++有點(diǎn)區(qū)別。
這篇文檔參考:參考文檔
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python實(shí)現(xiàn)定時(shí)同步本機(jī)與北京時(shí)間的方法
這篇文章主要介紹了python實(shí)現(xiàn)定時(shí)同步本機(jī)與北京時(shí)間的方法,涉及Python針對(duì)時(shí)間的操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
關(guān)于pygame.surface.blit()方法4個(gè)參數(shù)的使用
這篇文章主要介紹了關(guān)于pygame.surface.blit()方法4個(gè)參數(shù)的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
淺談pandas中shift和diff函數(shù)關(guān)系
下面小編就為大家分享一篇淺談pandas中shift和diff函數(shù)關(guān)系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04
Python 制作查詢(xún)商品歷史價(jià)格的小工具
這篇文章主要介紹了Python 如何制作查詢(xún)商品歷史價(jià)格的小工具,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下2020-10-10
python安裝庫(kù)的最詳細(xì)方法(以安裝pygame庫(kù)為例)
在學(xué)習(xí)了一個(gè)學(xué)期的python之后,我決定對(duì)pygame下手了,下面這篇文章主要給大家介紹了關(guān)于python安裝庫(kù)的最詳細(xì)方法,本文主要以安裝pygame庫(kù)為例,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
Python圖像的增強(qiáng)處理操作示例【基于ImageEnhance類(lèi)】
這篇文章主要介紹了Python圖像的增強(qiáng)處理操作,結(jié)合實(shí)例形式分析了使用ImageEnhance類(lèi)處理圖片的亮度、對(duì)比度、色度以及銳度等相關(guān)操作技巧,需要的朋友可以參考下2019-01-01

