【问题标题】:Check if an heap is a min-max heap检查堆是否是最小-最大堆
【发布时间】:2016-02-18 23:18:54
【问题描述】:

我写了一个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])(前提是两者都存在)。如果i 处的节点的祖父母不存在,h.grandparent_index(i) 返回None。

我的算法思路很简单。我从底部开始,检查我是否处于奇数水平。如果在一个均匀的水平上,那么我必须确保该元素大于其祖父母。如果我处于奇怪的水平,我必须确保它比它的祖父母小。

我的算法正确吗?我错过了一些观点吗?如果它是正确的,改进它的建议会被广泛接受。

最终我的实现可能对其他人有用。

编辑 1

我刚刚注意到我的函数检查偶数(和奇数)级别中的元素是否正确布置,但它不检查是否在self.heap[1] 或@987654331 找到最大元素@ 并且最小元素在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

【问题讨论】:

    标签: python python-3.x heap correctness minmax-heap


    【解决方案1】:

    更简单的方法是从堆中删除元素。算法是这样的:

    • 弹出 min-max 并将它们存储在数组中
    • 重复直到堆中不再有元素
    • 检查数组是否具有您期望的特征。

    在弹出堆中的所有元素后检查您生成的数组,您应该让偶数索引严格递增,奇数索引严格递减。如果不是这样,那么您的堆实现是错误的。

    【讨论】:

    • 您的解决方案可能也不错,但它涉及到堆的修改。在测试的情况下,它可以被使用,但不是其他的,除非你先复制堆的缓冲区,或者类似的东西。
    • 你是对的。但我相信你会想在删除 min-max 后测试堆,它仍然是一个有效的堆吗?也就是说,你的“heapfy”方法是否正确?
    【解决方案2】:

    您的算法缺少一些检查。考虑下面的示例,它不是最小最大堆,但通过了您的测试。将 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-03
      • 2012-12-31
      • 1970-01-01
      • 2011-03-07
      • 2012-05-26
      • 2011-10-11
      • 2014-10-24
      • 2010-11-08
      相关资源
      最近更新 更多