資料結構 堆(python實現)

2021-10-21 17:34:27 字數 3112 閱讀 9776

資料結構-堆(python實現)

用list來儲存堆元素,表尾端加入元素,首段作為堆頂(借鑑裘老師資料結構與演算法的書加上自己的理解)

# 堆:就是乙個完全二叉樹

class

heap

(object):

def__init__

(self, elist)

: self._elems =

list

(elist)

if elist:

self.buildheap(

)def

is_empty

(self)

:return

not self._elems

defpeek

(self)

:# 取堆頂的元素,並不是把堆頂元素給彈出

if self.is_empty():

raise valueerror(

'堆為空!'

)return self._elems[0]

defpush

(self, e)

:# 新插入乙個元素,鏈結在完全二叉樹最下層最右邊

none

)# 增加乙個位置

self.siftup(e,

len(self._elems)-1

)# 引數為新元素的值和列表的最後一位的下標值

""" 對於陣列裡的乙個下標 i,我們可以得到它的父親和孩子的節點對應的下標:(見書193頁)

parent = int((i-1) / 2) # 取整

left = 2 * i + 1

right = 2 * i + 2

"""defsiftup

(self, e, last)

:# e就是要上浮的元素,依次與它的父節點的值進行比較,last的值是最後乙個元素e的下標值,也就是列表的最大下標

elems, i, j = self._elems, last,

(last-1)

//2# j是最後乙個結點即i的父節點

while i >

0and e < elems[j]

:# e的值比e的父節點的值小

elems[i]

= elems[j]

# 把e的父節點的值下移和原來的e交換

i, j = j,

(j-1)//

2# 此時i為原來e的父節點的下標值,j為原來e的父節點的父節點的下標值,即再比較e與更上一層父節點的值

elems[i]

= e # 直到找不到比e小的父節點,就將e插入到此處,也就是鏈結到此父節點下

defpop

(self)

:if self.is_empty():

raise valueerror

elems = self._elems

e0 = elems[0]

# 堆頂是最優先元素,首先取出它的值,此時原來堆已經不是乙個完整的堆了

e = elems.pop(

)# list的pop首先彈出最後面乙個元素,給e放在堆頂再下沉恢復堆中元素的順序,去重新構成乙個完整的堆

iflen

(elems)

>0:

self.siftdown(e,0,

len(elems)

)"""

siftdown:始終比較父節點和兩個子節點的值,將小的往下放,然後將堆排好序,siftdown也是拿著元素去找位置,而不是先插入再去逐個交換

"""defsiftdown

(self, e, begin, end)

:# e是最後那個元素,begin是下標0,end是彈出堆頂後總的元素個數

elems , i, j = self._elems, begin, begin*2+

1# i=0,j是i的子節點

while j < end:

# 知道j還沒到最後乙個結點的下標值

if j+

1< end and elems[j+1]

< elems[j]

:# 並且j的兄弟節點也不是最後乙個結點,且左節點的值大於右節點的值

j +=

1# 如果左節點的值小於右節點的值,那麼e將會和它的右子節點換

if e < elems[j]

:# 如果e的值比e的子節點的值大,就將j結點往上提,大的在堆頂,小的往下放

break

elems[i]

= elems[j]

# elems[j]在三者中最小,上移,將j下標的值放在了堆頂,i=0為堆頂下標,但是各個元素的下標值沒變

i = j # 將堆頂結點的子節點下標j給i,表示將會將e插在此處

j = j *2+

1# 將j換成原來j子節點的下標值,然後while再去比較子節點值和e的大小,看看要不要交換,總之小的往下挪

elems[i]

= e # 如果e的子節點沒有比e更小的值,e就插入到i處,

defbuildheap

(self)

:# 用乙個元素的序列已經是堆的list去建立初始堆

end =

len(self._elems)

for i in

range

(end//2,

-1,-

1): self.siftdown(self._elems[i]

, i, end)

# 從列表的一半下標處通過向下篩選開始建立堆,

# 因為從end//2開始後面都是完全二叉樹的葉子節點,也就是每乙個已經是乙個堆

# 所以每一步就是在兩個已有的堆上面加上乙個根元素,並通過向下篩選調整成乙個堆

資料結構 堆的實現

普通的模板引數 template struct less template struct greater template 預設為小堆 class heap heap const t array,size t size int root heap.size 2 1 for root 0 root s...

(資料結構)堆的實現

堆總是一棵完全二叉樹 且 最大堆總滿足,堆中父節點的值總是大於等於其左右子節點的值 最小堆總滿足,堆中父節點的值總是小於等於其左右子節點的值。1.資料儲存 如下圖所示,如果自頂向下,自左向右依次將完全二叉樹中的每個節點標上序號 注 此處從1開始 並使用陣列儲存 注 陣列中下標0對應的位置未放置元素 ...

資料結構 棧 佇列 堆的python實現

二 佇列的python實現 三 堆的python實現 棧 佇列 堆是基礎的資料結構型別,其中棧是後進先出的資料結構 佇列是先進先出的資料結構 堆通常可以被看成一棵樹,又可以被分為最小堆和最大堆,最小堆是指堆中某個節點的元素總不大於其父節點的值 最大堆是指堆中某個元素總不小於其父節點的值。列表 lis...