[英]Check if an heap is a min-max heap
我編寫了一個min-max堆 ,即查找最小值和最大值的堆是常量操作。 現在,我想為類創建測試,因此我決定實現一個檢查堆是否為min-max-heap的函數。 在這里,但我不確定它是否100%正確。
def is_min_max_heap(h):
if not isinstance(h, MinMaxHeap):
return False
if h.heap:
for item in h.heap:
if not isinstance(item, HeapNode):
return False
for i, item in reversed(list(enumerate(h.heap))):
g = h.grandparent_index(i)
if g is not None:
if h.is_on_even_level(i):
if h.heap[g] > item:
return False
else:
if h.heap[g] < item:
return False
return True
請注意,該堆的元素由類HeapNode
表示,這就是為什么我要檢查self.heap
僅包含該類的對象的原因。 偶數級別例如為self.heap[0]
等。此堆的最小值位於self.heap[0]
。 最大值為max(self.heap[1], self.heap[2])
(假設兩者都存在)。 如果i
節點的祖父母不存在,則h.grandparent_index(i)
返回None
。
我算法的想法很簡單。 我從底部開始,然后檢查我是否處於奇數水平。 如果是偶數級,那么我必須確保該元素大於其祖父母。 如果我的水平很奇怪,我必須確保它比其祖父母小。
我的算法正確嗎? 我是否缺少一些要點? 如果是正確的話,就可以接受改進建議。
最終,我的實現可能對其他人有用。
編輯1
我剛剛注意到我的函數檢查偶數(和奇數)級中的元素是否正確相互放置,但不檢查是否在self.heap[1]
或self.heap[2]
找到最大元素self.heap[2]
並且最小元素在self.heap[0]
。
編輯2
我要根據編輯1和@goCards的答案添加新的更新代碼。
def is_min_max_heap(h) -> bool:
"""Returns `True` if `h` is a valid `MinMaxHeap` object. `False` otherwise."""
if not isinstance(h, MinMaxHeap):
return False
if h.heap:
for item in h.heap:
if not isinstance(item, HeapNode):
return False
if h.size() == 1:
return True
if h.size() == 2:
return max(h.heap) == h.heap[1] and min(h.heap) == h.heap[0]
if h.size() >= 3:
if (h.heap[0] != min(h.heap) or
(h.heap[1] != max(h.heap) and
h.heap[2] != max(h.heap))):
return False
for i, item in reversed(list(enumerate(h.heap))):
p = h.parent_index(i)
if p != -1:
if h.is_on_even_level(i):
if h.heap[p] < item:
return False
else:
if h.heap[p] > item:
return False
g = h.grandparent_index(i)
if g != -1:
if h.is_on_even_level(i):
if h.heap[g] > item:
return False
else:
if h.heap[g] < item:
return False
return True
一種更簡單的方法是從堆中刪除元素。 該算法將是這樣的:
彈出堆中的所有元素后,檢查生成的數組,您應該使偶數索引嚴格增加而奇數索引嚴格減少。 如果不正確,則您的堆實現是錯誤的。
您的算法缺少一些檢查。 考慮下面的示例,它不是最小-最大堆,但可以通過測試。 以5為根。 根有另一個分支,但為簡單起見未顯示。
使用您的算法,下面的堆被聲明為最小-最大堆,但它不滿足最小-最大堆屬性。 您的算法也需要檢查父節點。
編輯:最小-最大堆是滿足兩個屬性的二叉樹:
1)T呈堆狀
2)T是最小-最大有序的:存儲在偶數(奇數)級上的節點的值小於(大於)等於或等於存儲在其根為零級的后代(如果有)中的值。
for i, item in reversed(list(enumerate(h.heap))):
g = h.grandparent_index(i)
p = h.parent_index(i)
if g is not None and p is not None:
if h.is_on_even_level(i):
if item > h.heap[g]: pass #grandparent should be smallest in its subtree
else: return False
if item < h.heap[p]: pass #parent should be greatest in its subtree
else: return False
else: #odd level
if item < h.heap[g]: pass #grandparent should be greatest in its subtree
else: return False
if item > h.heap[p]: pass #parent should be smallest in its subtree
else: return False
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.