二叉堆有兩種:最小成員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。有根二叉樹還要滿足根結點的...