-1

I have an array arr = [1,2,1,3].

When I use heappush function to push the array elements as they are into a heap, the order of stays exactly the same as it is in the array:

arr = [1,2,1,3]
heap = []
for i in range(len(arr)):
    heapq.heappush(heap, arr[i])
print(heap)

Result: [1, 2, 1, 3]

Now, if I push the negative values of the elements of arr, the heap becomes sorted as it suppoed to be.

arr = [1,2,1,3]
heap = []
for i in range(len(arr)):
     heapq.heappush(heap,  - arr[i])    <---- Here
print(heap)

Result: [-3, -2, -1, -1]

I want to know why heappush sorts the array elements when their negative values are added to the heap but it does not do anything when the positive values are pushed into the heap.

Gerd
  • 2,568
  • 1
  • 7
  • 20
Amir Jalilifard
  • 2,027
  • 5
  • 26
  • 38
  • 1
    Have you seen this https://stackoverflow.com/a/14282603/914874 answer? – Eduardo Jan 04 '20 at 14:42
  • 1
    The contents of a heap are not supposed to be sorted. That's why there's a separate term "heap" instead of just calling them "sorted lists". – user2357112 Jan 04 '20 at 14:51

1 Answers1

4

This is known as the heap invariant and you can see this stated in the docs as well where it says:

Heaps are binary trees for which every parent node has a value less than or equal to any of its children. This implementation uses arrays for which heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2] for all k, counting elements from zero. For the sake of comparison, non-existing elements are considered to be infinite. The interesting property of a heap is that its smallest element is always the root, heap[0].

Take note of where it says that the smallest element is always the root, heap[0], which is evident by looking at your data. Also take note how both of your lists observe the properties listed heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2] for all k.

Now if we take a look at your lists we can see the properties are observed:

inf = float('inf')
arr = [1, 2, 1, 3]

for i in range(len(arr)):
    x = arr[i]
    try:
        y = arr[2 * i + 1]
    except IndexError:
        y = inf
    print('x <= y is {}'.format(x <= y))

x <= y is True
x <= y is True
x <= y is True
x <= y is True

The same applies if you use the negative array. Hope that helps clear things up for you.

gold_cy
  • 13,648
  • 3
  • 23
  • 45
  • 1
    Note that it doesn't *have* to be a binary tree, either. You could use a higher-degree tree, at the cost of making the implementation more complex. The benefit would be better cache locality. – chepner Jan 04 '20 at 14:52