Python自定義二叉堆類

2021-09-18 07:30:13 字數 3042 閱讀 8095

二叉堆有兩種:最小成員key排在隊首的稱為「最小堆(min heap)」;最大key排在隊首的是「最大堆(max heap)」,這是一種優先佇列的實現方式。

優先佇列的出隊(dequeue)操作和佇列一樣,都是從隊首出隊。但在優先佇列內部,資料項的次序是由它們的「優先順序」來確定的:有最高優先順序的資料項排在隊首,而優先順序最低的資料項則排在隊尾。這樣,優先佇列的入隊(enqueue)操作就需要將資料項擠到佇列前方。

完全二叉樹:指每個內部節點都有兩個子節點,最多可有乙個節點例外。

如果完全樹的節點在列表中的位置為p(p>0),那麼其左子節點的位置就為2p,右子節點的位置就為2p+1。

找任意節點的父節點的方法:若節點在列表中的位置為n,那麼其父節點的位置就是n//2。

堆次序:是指堆中任意乙個節點x,其父節點p中的key(節點值)均小於或等於x中的key。

# 自定義最小堆類

class binheap(object):

# 構造二叉堆

def __init__(self):

# 表首下標為0的項並沒有用到,但為了後面**可以用到簡單的整數乘除法,仍保留它

self.heaplist = [0]

self.currentsize = 0

# 上浮函式,i為節點位置,判斷新節點是否比父節點小,若小則新節點交換上浮以保證堆次序

def percup(self, i):

while i // 2 > 0: #若父節點的位置大於0,則迴圈

if self.heaplist[i] < self.heaplist[i // 2]: #若子節點值小於父節點值,則交換位置

self.heaplist[i], self.heaplist[i // 2] = self.heaplist[i // 2], self.heaplist[i]

i = i // 2 #更新當前節點位置,判斷是否需要繼續上浮

# 插入函式,新增新節點

def insert(self, k):

self.currentsize += 1 #更新新節點位置

self.percup(self.currentsize) #檢查新節點是否需要上浮,以維持堆次序

# 下沉函式,i為節點位置,判斷子節點是否比父節點小,若小則父節點交換下沉以保證堆次序

def percdown(self, i):

# 若i*2<=當前節點位置(最後乙個節點),說明待測節點有子節點,則迴圈

while (i * 2) <= self.currentsize:

mc = self.minchild(i) #獲取i的最小子節點位置

if self.heaplist[i] > self.heaplist[mc]: #若i的值》其最小子節點值,則交換位置

self.heaplist[i], self.heaplist[mc] = self.heaplist[mc], self.heaplist[i]

i = mc #更新待檢測下沉節點位置,判斷是否需要繼續下沉

# 獲取最小子節點位置

def minchild(self, i):

if i * 2 + 1 > self.currentsize:#i的右子節點位置》當前節點位置(最後乙個節點),則

return i * 2 #返回左子節點位置,因為i沒有右子節點

else: #若i有右子節點,則

if self.heaplist[i * 2] < self.heaplist[i * 2 + 1]: #若i的左子節點值《右子節點值,則

return i * 2 #返回左子節點位置

else:

return i * 2 + 1 #返回右子節點位置

# 刪除最小節點

def delmin(self):

retval = self.heaplist[1] #獲取最小節點,即根節點

# 以下4行**是為了維持堆結構和堆次序

self.heaplist[1] = self.heaplist[self.currentsize] #將當前節點,即最後乙個節點賦值給根節點,不能直接刪除根節點,因為要維持堆結構

self.heaplist.pop() #刪除堆最後乙個節點,因為此節點值已交換給了根節點

self.currentsize -= 1 #當前節點位置減1,因為刪除了乙個節點

self.percdown(1) #檢查新的根節點是否需要下沉,以維持堆次序

return retval #返回刪除的最小節點

# 無序列表構建二叉堆

def buildheap(self, alist):

self.currentsize = len(alist) #獲取列表最後乙個位置

self.heaplist = [0] + alist[:] #列表0位置新增0元素,便於後續計算

i = len(alist) // 2 #獲取最後乙個節點的父節點位置

while i > 0:

self.percdown(i) #判斷父節點是否需要下沉

i = i -1 #將待檢測節點位置更新為上乙個節點位置

bh = binheap() #例項化最小堆類

bh.buildheap([9,5,6,2,3]) #無序列表構建最小堆

print(bh)

print(bh.delmin()) #刪除當前最小節點

print(bh.delmin())

print(bh.delmin())

bh.insert(7) #新增新節點

print(bh.delmin())

print(bh.delmin())

結果為:

<__main__.binheap object at 0x00000000026ff630>23

567

自定義二叉搜尋樹

public class binarysearchtree private node root insert 1.判斷根節點是否存在,不存在則建立新的根節點 2.根據二叉搜尋樹的性質 左節點 根節點 右節點 進行一種正確的插入方式 public void insert int val node pa...

python自定義類

設計乙個person類的3種方式 1 使用內建型別list person mike 23,male 0 姓名,1 年紀,2 性別 print person 0 person 1 person 2 2 使用字典型別dic person1 person2 print person1 name perso...

java自定義二叉樹

今天學習的是二叉樹的相關知識。二叉樹是樹的一種,因為他每個結點最多只有2個子結點,所以叫做二叉樹。鍊錶實際上很像是樹的特殊情況。二叉樹有很多種,其中著名的就有二叉查詢樹和霍夫曼樹。quote 二叉樹在圖論中是這樣定義的 二叉樹是乙個連通的無環圖,並且每乙個頂點的度不大於2。有根二叉樹還要滿足根結點的...