HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Efficient bookkeeping in heap

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
efficientheapbookkeeping

Problem

I'm trying to implement a heap using list data structure. I'd also like to keep track of the position of elements in the list in order to enable easy deletion. My implementation involves looping through the entire list to update the positions after an insert/delete combo. I'm afraid this raises the time complexity from O(log n) to O(n). Is there a better way of keeping track of elements' position? Currently, update method is what takes care of the bookkeeping.

```
class heap():
''' Min-Heap'''
def __init__(self,G):
self.list=[0] #to ease dealing with indices, an arbitrary value at index 0
self.pos={} #holds position of elements with respect to list
self.G = G #Graph, contains the score for each element in G[element][2]
def update_pos(self):
self.pos = {}
for i in xrange(1,len(self.list)):
self.pos[self.list[i]]=i

def percUp(self): #percolate up, called by insert method
start = len(self.list)-1
while start//2>0:
if self.G[self.list[start/2]][2] > self.G[self.list[start]][2]:
self.list[start/2],self.list[start] = self.list[start],self.list[start/2]
start = start//2

def insert(self,element):
self.list.append(element)
self.percUp()
self.update_pos()

def percDown(self,start=1): #percolate down, called by extract_min method
while 2*start self.G[self.list[min_ind]][2]:
self.list[start],self.list[min_ind] = self.list[min_ind],self.list[start]
start = min_ind

def extract_min(self):
self.list[-1],self.list[1] = self.list[1],self.list[-1]
small = self.list[-1]
self.list = self.list[:-1]
self.percDown()
self.update_pos()
return small

def delete(self,pos):
self.list[-1],self.list[pos] = self.list[pos],self.list[-1]
self.pos.pop(self.list[pos])
self.list = self.list[:-1]
self.percDown(pos)
self.update_pos()

def getMinInd(self,start):
if 2*start+1 > len(self.list)-1:
return 2*start
else:

Solution

-
Instead of calling update_pos at the end of a heap operation, update it as you go along. For example, percUp becomes:

cur_pos = len(self.list) - 1
parent_pos = cur_pos // 2
while parent_pos:
    cur = self.list[cur_pos]
    parent = self.list[parent_pos]
    if self.G[parent][2] > self.G[cur][2]:
        self.list[parent_pos] = cur
        self.pos[cur] = parent_pos
        self.list[cur_pos] = parent
        self.pos[parent] = cur_pos
    cur_pos = parent_pos
    parent_pos //= 2


And similarly for percDown.

-
Having written that, a simpler approach to deletion from a heap is simply to leave the object in the heap but mark it somehow as deleted. Then when you extract the minimum you check to see if it was marked as deleted, and if it was, you throw it away and extract another one.

-
If you use the "mark object as deleted" method, then you would be able to use Python's built-in heapq module (see in particular the "Priority Queue Implementation Notes"). See this answer for an example implementation.

-
It looks (from the name "G" for the scores) as though you are using this to implement the priority queue of unvisited nodes in the A search algorithm. But then it is not clear why you need to delete items from the middle of the heap—in the A algorithm this never happens (an item is only deleted when it is popped as the minimum item). So you could just not implement deletion, and since the pos dictionary is only used by the deletion method, you wouldn't have to maintain it, and so you could just use Python's built-in heaps directly. See this answer for an example.

Code Snippets

cur_pos = len(self.list) - 1
parent_pos = cur_pos // 2
while parent_pos:
    cur = self.list[cur_pos]
    parent = self.list[parent_pos]
    if self.G[parent][2] > self.G[cur][2]:
        self.list[parent_pos] = cur
        self.pos[cur] = parent_pos
        self.list[cur_pos] = parent
        self.pos[parent] = cur_pos
    cur_pos = parent_pos
    parent_pos //= 2

Context

StackExchange Code Review Q#139538, answer score: 2

Revisions (0)

No revisions yet.