2

I am using this library for a heap:

from Queue import PriorityQueue

I need to trigger a heapify because in this priority queue i am inserting a node class and the prioirty queue is ordered based on node.val like this:

class Node():
   __init__(self,val,text):
       self.val = val
       self.text = text

and my pq:

pq = PriorityQueue()
first = Node(1,'abcd')
pq.put((first.val,first))

xyz = Node(10,'asdf')
pq.put((xyz.val,xyz))


fsa = Node(7,'asdsbcd')
pq.put((fsa.val,fsa))

now it works fine but if i want to for example change first nodes value like this:

first.val = 100

is there a method like pq.heapify() or something..

how do i call a heapify method so that it can sort it? because if i dont then it will be sort the list and assume first still is 1 not 100.

  • standard heap classes usually have only the methods for insertion, top lookup and top removal, i.e. the modification of the internal data structure is not allowed. you will need to implement your own priority queue – mangusta Feb 14 '20 at 16:01
  • @mangusta hmmm, what about a remove a certain node? is there a method? so that i can remove it and then reinsert it with the updated val. – asdad asdasd Feb 14 '20 at 16:03
  • that came to my mind as well, but I'm not sure if there is such a method in python. Java's priority queue has a method `remove(Object o)` – mangusta Feb 14 '20 at 16:05
  • I'm not sure if this library can do that. However, consider the heapify method from the heapq library Python provides: https://docs.python.org/2/library/heapq.html#heapq.heapify – LeKhan9 Feb 14 '20 at 16:56

1 Answers1

1

I believe it would be better to use heapq library for your heap.

Then you can use a process from this answer to update the min value in the heap as follows.

Advantages:

  1. Approach allows updating smallest element using replace.
  2. Takes only O(log(n)) to update the value of the smallest element (i.e. changing first from 1 to 100)
  3. Faster than using Heapify when only one item needs to be updated (which takes O(n))

Code

import heapq

class Node():
  def __init__(self,val,text):
       self.val = val 
       self.text = text
  def __str__(self):   # Add a method to node to string for display
    return f'{self.val}, {self.text}'

class MyHeap(object):
  """The class keeps an internal list, where each element is a tuple.
    The first tuple element is the priority (val), calculated at element insertion 
    time, using the key parameter, passed at Heap instantiation"""
  def __init__(self, initial=None, key=lambda x:x.val):
    self.key = key
    if initial:
      self._data = [(key(item), item) for item in initial]
      heapq.heapify(self._data)
    else:
      self._data = []

  def push(self, item):
    heapq.heappush(self._data, (self.key(item), item))

  def pop(self):
    return heapq.heappop(self._data)[1]

  def replace(self, item):
    # Pops min element and adds a new element
    v = self.pop()
    self.push(item)
    return v

Testing

Test 1. Add Elements and dump heap

# Add elements
pq = MyHeap()
first = Node(1,'abcd')
pq.push(first)

xyz = Node(10,'asdf')
pq.push(xyz)

fsa = Node(7,'asdsbcd')
pq.push(fsa)

# Dump elements in order
print('Initial Ordering')
while pq._data:
  print(pq.pop())

Result

Initial Ordering
1, abcd
7, asdsbcd
10, asdf

Test 2. Remove smallest and add as new element with larger value with new value

# Add elements
pq.push(first)
pq.push(xyz)
pq.push(fsa)

# Update first element using replace
first.val = 100
pq.replace(first)

print('\nNew Ordering')
while pq._data:
  print(pq.pop())

Result

New Ordering
7, asdsbcd
10, asdf
100, abcd

Test 3: Add Elements as List

print('\nUsing List')
pq = MyHeap([first, xyz, fsa])
while pq._data:
  print(pq.pop())

Result

Using List
7, asdsbcd
10, asdf
100, abcd
DarrylG
  • 16,732
  • 2
  • 17
  • 23
  • ill accept urs since it looks fast, but i did something a bit different, easier to code tho - i just deleted the whole heap and put it in an array, and then rebuilt the heap making sure the new value is updated. – asdad asdasd Feb 16 '20 at 21:44
  • @asdadasdasd -- The issue is modifying an element the way you mention takes O(n) time (i.e. since Heapify is O(n)). Performing an update using the method suggested here takes O(log(n)) which is much faster. Meaning for n ~10^6, the above method is ~20, while using Heapify ~O(n^6), which is 50,00 times slower. However, if you're not doing this very often or the number of elements is small then it doesn't matter. – DarrylG Feb 16 '20 at 22:54
  • yeah but im not on leetcode - school work - so less coding for me is better. – asdad asdasd Feb 17 '20 at 12:55
  • @asdadasdasd-- As the [Zen of Python says](https://www.python.org/dev/peps/pep-0020/): "Simple is better than complex". So if your technique works and is simpler to code then yes, it's better to use it. More complex code is required only for more complex problems. – DarrylG Feb 17 '20 at 13:35