我写了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
是否仅包含该类对象的原因。甚至级别例如是0,2,4等。此堆的最小值位于self.heap[0]
。最大值为max(self.heap[1], self.heap[2])
(前提是两者都存在)。如果h.grandparent_index(i)
处的节点的祖父母不存在,则None
会返回i
。
我的算法的想法非常简单。我从底部开始,然后检查我是否处于奇怪的水平。如果在一个均匀的水平上,那么我必须确保该元素大于其祖父母。如果我处于奇怪的水平,我必须确保它比祖父母小。
我的算法是否正确?我错过了一些观点吗?如果它是正确的,那么改进它的建议是被广泛接受的。
最终我的实施可能对其他人有用。
修改1
我刚刚注意到我的函数检查偶数(和奇数)级别的元素是否正确相互配置,但是它不会检查是否在self.heap[1]
或者self.heap[2]
处找到了最大元素self.heap[0]
并且最小元素位于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
。
修改2
我正在根据编辑1和@goCards的答案添加新的更新代码。
public class YourClass
{
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
}
答案 0 :(得分:1)
更简单的方法是从堆中删除元素。算法将是这样的:
在弹出堆中的所有元素后检查生成的数组,应该使得偶数索引严格增加,奇数索引严格减少。如果不是这样,那么堆实现是错误的。
答案 1 :(得分:0)
您的算法缺少一些检查。考虑下面的示例,它不是最小 - 最大堆,而是通过您的测试。考虑5是根。根有另一个分支但是为了简单起见没有显示。
使用您的算法,下面的堆被声明为最小 - 最大堆,但它不满足最小 - 最大堆属性。您的算法也需要检查父节点。
编辑:最小 - 最大堆是一个满足两个属性的二叉树:
1)T具有堆形
2)T是min-max ordered:存储在节点上的值 偶数(奇数)水平小于(大于)或等于 存储在其后代的值(如果有的话) 根位于零级别。
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