Running Median of Data Stream
Given an input stream of n integers the task is to insert integers to stream and print the median of the new stream formed by each insertion of x to the stream.
class MaxHeap(object):
def __init__(self):
self.heap_list = [0]
self.current_size = 0
def empty(self):
return (self.current_size==0)
def perc_up(self,i):
while i//2>0:
if self.heap_list[i] > self.heap_list[i//2]:
self.heap_list[i],self.heap_list[i//2] = self.heap_list[i//2],self.heap_list[i]
i = i//2
def insert(self,val):
self.heap_list.append(val)
self.current_size+=1
self.perc_up(self.current_size)
def get_child(self,i):
if 2*i+1 > self.current_size:
return 2*i
else:
if self.heap_list[2*i] > self.heap_list[2*i+1]:
return 2*i
else:
return 2*i+1
def perc_down(self,i):
while 2*i<=self.current_size:
child_id = self.get_child(i)
if self.heap_list[child_id] > self.heap_list[i]:
self.heap_list[child_id],self.heap_list[i] = self.heap_list[i],self.heap_list[child_id]
i = child_id
def peek(self):
if self.current_size:
return self.heap_list[1]
else:
return None
def del_max(self):
if self.current_size:
max_val = self.heap_list[1]
self.heap_list[1] = self.heap_list[-1]
self.heap_list.pop()
self.current_size-=1
self.perc_down(1)
return max_val
else:
return None
class MinHeap(object):
def __init__(self):
self.heap_list = [0]
self.current_size = 0
def empty(self):
return (self.current_size==0)
def peek(self):
if self.current_size:
return self.heap_list[1]
else:
return None
def perc_up(self,i):
while i//2>0:
if self.heap_list[i] < self.heap_list[i//2]:
self.heap_list[i],self.heap_list[i//2] = self.heap_list[i//2],self.heap_list[i]
i = i//2
def insert(self,val):
self.heap_list.append(val)
self.current_size+=1
self.perc_up(self.current_size)
def get_child(self,i):
if 2*i+1>self.current_size:
return 2*i
else:
if self.heap_list[2*i] < self.heap_list[2*i+1]:
return 2*i
else:
return 2*i+1
def perc_down(self,i):
while 2*i<=self.current_size:
child_id = self.get_child(i)
if self.heap_list[child_id] < self.heap_list[i]:
slef.heap_list[child_id],self.heap_list[i] = self.heap_list[i],self.heap_list[child_id]
i = child_id
def del_min(self):
if self.current_size:
min_val = self.heap_list[1]
self.heap_list[1] = self.heap_list[-1]
self.heap_list.pop()
self.current_size -=1
self.perc_down(1)
return min_val
else:
return None
def running_median(data):
left_max_heap = MaxHeap()
right_min_heap = MinHeap()
for val in data:
if left_max_heap.empty() or left_max_heap.peek() > val:
left_max_heap.insert(val)
else:
right_min_heap.insert(val)
if abs(left_max_heap.current_size - right_min_heap.current_size )>1:
if left_max_heap.current_size > right_min_heap.current_size:
left_max = left_max_heap.del_max()
right_min_heap.insert(left_max)
else:
right_min = right_min_heap.del_min()
left_max_heap.insert(right_min)
if right_min_heap.current_size == left_max_heap.current_size:
print (right_min_heap.peek()+left_max_heap.peek())/2.0
else:
median = right_min_heap.peek() if right_min_heap.current_size > left_max_heap.current_size else left_max_heap.peek()
print median