簡體   English   中英

檢查堆是否是最小-最大堆

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM