1

I have this function def validate(self) which should check if a given array is a valid min heap. I think it works but because my arrays have None at the beginning like [None, 2, 3, 5] it seems to run into problems and give me the error '<' not supported between instances of 'int' and 'NoneType'

How can i skip over the none value in my code?

def validate(self):
    """
    Validates the heap. Returns True if the heap is a valid min-heap, and
    False otherwise.

    """

    n = self.__len__() 
    for i in range(int((n - 2) / 2) + 2):

        if self._items[2 * i + 1] < self._items[i]: 
            return False

        if (2 * i + 2 < n and self._items[2 * i + 2] > self._items[i]): 
            return False
    return True

New code:

def validate(self):
    """
    Validates the heap. Returns True if the heap is a valid min-heap, and
    False otherwise.

    """

    n = self.__len__() 
    for i in range(int((n - 2) / 2) + 2):
        if self._items[i] != None:
            if self._items[2 * i + 1] < self._items[i]: 
                return False

        if (2 * i + 2 < n and self._items[2 * i + 2] > self._items[i]): 
            return False

Error:

  File "<doctest __main__.MinHeap.validate[8]>", line 1, in <module>
    h.validate()
  File "x-wingide-python-shell://114699264/2", line 219, in validate
TypeError: '>' not supported between instances of 'int' and 'NoneType'
  • `None` is not comparable with other elements, so it should not be a part of the heap array. I think that the resulting binary tree is not balanced... – Kate Melnykova Jan 30 '21 at 03:01
  • 1
    In using an array to implement a heap the root node can be at index 0 or 1 i.e. [Why in a heap implemented by array the index 0 is left unused](https://stackoverflow.com/questions/22900388/why-in-a-heap-implemented-by-array-the-index-0-is-left-unused#:~:text=The%20string%20x%20gives%20the,%22take%20the%20right%20child%22.). Since None is at index 0 this seems like the root node is at index 1, so the array should be checked accordingly. – DarrylG Jan 30 '21 at 03:25

2 Answers2

0

Change

    for i in range(int((n - 2) / 2) + 2):
        if self._items[2 * i + 1] < self._items[i]
            return False

        if (2 * i + 2 < n and self._items[2 * i + 2] > self._items[i]): 
            return False

to

    _items = list(filter(None, self._items)) # delete all Nones in the list, save the cleaned list into a local variable in case you want to use the unmodified list somewhere else
    for i in range(int((n - 2) / 2) + 2):
        if _items[2 * i + 1] < _items[i]: 
            return False

        if (2 * i + 2 < n and _items[2 * i + 2] > _items[i]): 
            return False

Like that, it will remove all Nones from the list first, and only then do the comparison.

TheEagle
  • 5,808
  • 3
  • 11
  • 39
0

Rather than checking each non-leaf node against its left child and its right child (if it has one), it is simpler to check each non-root node against its parent.

def validate(self):
    n = len(self._items)
    for i in range(2, n):
        if self._items[i // 2] > self._items[i]: 
            return False
    return True

You can also use a comprehension with all:

def validate(self):
    n = len(self._items)
    return all(self._items(i // 2) <= self._items[i] for i in range(2, n))
kaya3
  • 47,440
  • 4
  • 68
  • 97