我写了一个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
请注意,这个堆的元素用 class 表示HeapNode
,这就是我检查是否self.heap
只包含该类的对象的原因。偶数级别例如为 0、2、4 等。此堆的最小值位于self.heap[0]
. 最大值是max(self.heap[1], self.heap[2])
(前提是两者都存在)。如果节点 at 的祖父母不存在,则h.grandparent_index(i)
返回。None
i
我的算法的想法很简单。我从底部开始,检查我是否处于奇数水平。如果在一个均匀的水平上,那么我必须确保该元素大于其祖父母。如果我处于奇怪的水平,我必须确保它比它的祖父母小。
我的算法正确吗?我错过了一些观点吗?如果它是正确的,改进它的建议会被广泛接受。
最终我的实现可能对其他人有用。
编辑 1
我刚刚注意到我的函数检查偶数(和奇数)级别中的元素是否正确布置,但它不检查最大元素是否位于self.heap[1]
或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