1

I have a simple heap defined as a list of lists. I was using heapop from the heapq module to extract the list with the smallest key (which I learnt is implicitly the first element of the inner list). But in the following case, the pop operation seems to be giving unusual results.

Can someone explain why?

heap=[[0, 0, 0], [inf, 1, 1], [inf, 2, 2], [5, 3, 3], [inf, 4, 4]]

heapq.heappop(heap)

[0, 0, 0]

heapq.heappop(heap)

[inf, 1, 1]

heapq.heappop(heap)

[5, 3, 3]

heapq.heappop(heap)

[inf, 2, 2]

heapq.heappop(heap)

[inf, 4, 4]

Community
  • 1
  • 1
Janmajay
  • 53
  • 1
  • 6

1 Answers1

5

The problem is that you are using heapq on a list that is not a heap. The documentation discusses using the heapify command, and that indeed works:

>>> import heapq
>>> from numpy import inf
>>> heap=[[0, 0, 0], [inf, 1, 1], [inf, 2, 2], [5, 3, 3], [inf, 4, 4]]
>>> heapq.heapify(heap)
>>> heap
[[0, 0, 0], [5, 3, 3], [inf, 2, 2], [inf, 1, 1], [inf, 4, 4]]
>>> heapq.heappop(heap)
[0, 0, 0]
>>> heapq.heappop(heap)
[5, 3, 3]
>>> heapq.heappop(heap)
[inf, 1, 1]
>>> heapq.heappop(heap)
[inf, 2, 2]
>>> heapq.heappop(heap)
[inf, 4, 4]
Dr Xorile
  • 967
  • 1
  • 7
  • 20
  • What if I modify inf to some value while performing some operations? Would I have to run heapify again? – Janmajay Apr 26 '16 at 22:31
  • If you might change the order, then you would need to heapify again. It's not magic - it's just a standardized sorting algorithm. One option is to heappop out the list you want to change and then heappush in the new list. If you want to keep the list as a heap, then you must only modify it using heapq operations – Dr Xorile Apr 26 '16 at 22:43
  • heapq.heapreplace is a function that will allow you to do both the pop and the push at the same time – Dr Xorile Apr 26 '16 at 22:44
  • Check the [heapq documentation](https://docs.python.org/2/library/heapq.html) - it's pretty good. – Dr Xorile Apr 26 '16 at 22:45
  • I am implementing Dijkstra's algorithm where the first value (representing distance from source) gets modified as better paths are formed. I was just changing values using list assignment uptill now. Do you have any better suggestions? – Janmajay Apr 26 '16 at 22:46
  • It depends what you're trying to do. If you're just practicing code, then heapq.heapreplace would seem to be the way forward. If you're looking for a good implementation of dijkstra's algorithm, obviously many exist already. [Networkx](https://networkx.github.io/) is probably one of the best graph theory implementations (and pretty fast!). There's a simple one [here](https://bytes.com/topic/python/insights/877227-dijkstras-algorithm-finding-shortest-route), if you're looking for something small and self-contained. – Dr Xorile Apr 26 '16 at 22:56