參考自 mooc資料結構與演算法python版
二、二叉堆的實現
佇列有一種變體稱為「優先佇列」,優先佇列的出隊跟佇列一樣從隊首出隊,但在優先佇列內部, 資料項的次序卻是由「優先順序」來確定:高優先順序的資料項排在隊首,而低優先順序的資料項則排在後面。這樣,優先佇列的入隊操作就比較複雜,需要將資料項根據其優先順序盡量擠到佇列前方。
有什麼方案可以用來實現優先佇列?
二叉堆能夠將優先佇列的入隊和出隊複雜度都保持在o(l
ogn)
o(log n)
o(logn
)。二叉堆的有趣之處在於, 其邏輯結構上像二叉樹, 卻是用非巢狀的列表來實現的
adt binaryheap的操作定義如下:
函式含義
binaryheap()
建立乙個空二叉堆物件
insert(k)
將新key加入到堆中
findmin()
返回堆中的最小項,最小項仍保留在堆中
delmin()
返回堆中的最小項,同時從堆中刪除
isempty()
返回堆是否為空
size()
返回堆中key的個數
buildheap(list)
從乙個key列表建立新堆
【**】:
from pythonds.trees.binheap import binheap
bh = binheap(
)bh.insert(5)
bh.insert(7)
bh.insert(3)
bh.insert(11)
print
(bh.delmin())
print
(bh.delmin())
print
(bh.delmin())
print
(bh.delmin(
))
為了使堆操作能保持在對數水平上, 就必須採用二叉樹結構;
同樣, 如果要使操作始終保持在對數數量級上, 就必須始終保持二叉樹的「平衡」
– 樹根左右子樹擁有相同數量的節點
我們採用「完全二叉樹」的結構來近似實現「平衡」
葉節點最多隻出現在最底層和次底層,而且最底層的葉節點都連續集中在最左邊,每個內部節點都有兩個子節點, 最多只有1個節點例外,比如下圖中的18號節點。
如果節點的下標為p,那麼其左子節點下標為2p,右子節點為2p+1,其父節點下標為p//2
堆的性質:在任何一條路徑上,它都是乙個有序的佇列。
採用乙個列表來儲存堆資料,其中表首下標為0的項無用,但為了後面**可以用到簡單的整數乘除法,仍保留它。
class
binheap
:def
__init__
(self)
: self.heaplist =[0
] self.currentsize =
0
def
percup
(self,i)
:while i//
2>0:
#沿著路徑往上
if self.heaplist[i]
< self.heaplist[i//2]
:#如果小於父節點
tmp = self.heaplist[i//2]
#跟父節點交換
self.heaplist[i//2]
= self.heaplist[i]
self.heaplist[i]
= tmp
i = i //
2#再往上一級
definsert
(self,k)
:#新增到末尾
self.currentsize = self.currentsize +
1#size+1
self.percup(self.currentsize)
# 上浮,比較大小
移走根節點heaplist[1],並保證堆次序不被破壞。
先用最後乙個節點來代替根節點,再將新的根節點沿著一條路徑「下沉」,直到比兩個子節點都小。
「下沉」路徑的選擇:如果比子節點大,那麼選擇兩個子節點中較小的子節點交換下沉。示 意圖如下:
左子節點9,右子節點 11,27和9交換。
左子節點14,右子節點 18,27和14交換。
左子節點33,右子節點 17,27和17交換。
#找出較小的子節點
if self.heaplist[i]
> self.heaplist[mc]
:#如果大於子節點,交換下沉
tmp = self.heaplist[i]
self.heaplist[i]
= self.heaplist[mc]
self.heaplist[mc]
= tmp
i = mc #沿路徑向下
defminchild
(self, i)
:#找出較小的子節點
if i *2+
1> self.currentsize:
return i*
2else
:if self.heaplist[i*2]
< self.heplist[i*2+
1]:return i*
2else
:return i*2+
1def
delmin
(self)
: retval = self.heaplist[1]
#移走堆頂
self.heaplist[1]
= self.heaplist[self.currensize]
self.currentsize -=
1 self.heaplist.pop(
) self.percdown(1)
#新頂下沉
return retval
下沉法,能夠將總代價控制在o(n
)o(n)
o(n)
【**】:
def
buildheap
(self, alist)
: i =
len(alist)//2
#從最後節點的父節點開始
self.currentsize =
len(alist)
self.heaplist =[0
]+ alist[:]
print
(len
(self.heaplist)
,i)while
(i>0)
:print
(self.heaplist, i)
self.percdown(i)
i -=
1print
(self.heaplist, i)
資料結構與演算法 優先佇列
優先佇列按照佇列的方式正常入隊,但按照優先順序出隊。有兩種實現方式 堆 二插堆 多項式堆等等 和二叉搜尋樹。這裡重點講解二叉堆,關於二叉搜尋樹的內容見這篇文章。堆是一種特殊的完全二叉樹。大根堆 完全二叉樹的任一節點都比其孩子節點大。小根堆 完全二叉樹的任一節點都比其孩子節點小。堆的向下調整 假設根節...
資料結構與演算法 優先佇列
英雄聯盟遊戲裡面防禦塔都有乙個自動攻擊功能,小兵排著隊進入防禦塔的攻擊範圍,防禦塔先攻擊靠得最近的小兵,這時候大炮車的優先順序更高 因為系統判定大炮車對於防禦塔的威脅更大 所以防禦塔會優先攻擊大炮車。而當大炮車陣亡,剩下的全部都是普通小兵,這時候離得近的優先順序越高,防禦塔優先攻擊距離更近的小兵。優...
python資料結構與演算法
coding utf 8 import sys 使用以下語句將引數的str格式轉換為int格式 l list map int sys.argv 1 split target int sys.argv 2 def binarysearch print l print target left 0 rig...