def merge_sorted_lists(): k = 10 n = 10 min_value = 0 max_value = 30 sorted_lists = generate_sorted_lists(k,n,min_value,max_value) sorted_list = SingleLinkedList() heap = MinHeap([], 0) # fill in the 1st batch for i, l in sorted_lists.items(): heap.add(IdAndValue(i, l.pop(0))) while len(sorted_lists) > 0: item = heap.pop() sorted_list.append(item.get_value()) list_id = item.get_id() if list_id in sorted_lists: value = sorted_lists[list_id].pop(0) if len(sorted_lists[list_id]) <= 0: sorted_lists.pop(list_id) heap.add(IdAndValue(list_id, value)) else: list_id, list = sorted_lists.items()[0] heap.add(IdAndValue(list_id, list.pop(0))) if len(list) <= 0: sorted_lists.pop(list_id) while not heap.is_empty(): sorted_list.append(heap.pop()) print k*n, len(sorted_list), sorted_list
def sort_k_sorted(arr, k): ans = [] h = MinHeap() for i in range(k + 1): h.insert(arr[i]) for i in range(k + 1, len(arr)): smallest = h.extract() ans.append(smallest) h.insert(arr[i]) while not h.is_empty(): smallest = h.extract() ans.append(smallest) return ans
def shortest_paths(self, v): ''' Computes the shortest path distances from a source vertex to all other vertices using Dijkstra's algorithm. ''' processed = {} # mapping of processed vertices to geodesic distance candidates = {} # mapping of candidate vertices to their Dijkstra scores; exists for convenience of O(1) lookups trace = [] # stores edges in order of processing; used to extract shortest paths def dijkstra_score(src, dest): return processed[src] + self.getWeight(src, dest) # Initialize Dijkstra scores for n in self.nodes: if n == v: processed[n] = 0 for dest in self.edges[n]: score = dijkstra_score(n, dest) if dest not in candidates or score < candidates[dest]: candidates[dest] = score else: if n not in candidates: candidates[n] = float('inf') # heapify node/score tuples, provide comparison key unprocessed = MinHeap(list(candidates.items()), lambda x:x[1]) # compute shortest paths while not unprocessed.is_empty(): n,s = unprocessed.extract_min() processed[n] = s candidates.pop(n) if len(trace) == 0: trace.append(Edge(v, n)) # Investigate KeyError when using WeightedEdge else: src = trace[-1].getDestination() trace.append(Edge(src, n)) # Investigate KeyError when using WeightedEdge for dest in self.edges[n]: if dest in candidates: unprocessed.delete((dest, candidates[dest])) score = dijkstra_score(n, dest) best = min(candidates[dest], score) candidates[dest] = best unprocessed.insert((dest, best)) return (processed, PathFinder(trace))
class MedianMaintenance: def __init__(self): self.hlow_heap = MaxHeap() self.hhigh_heap = MinHeap() def compute_median(self, i): self.insert_heap(i) self.balance_heap() return self.median() def balance_heap(self): if self.hhigh_heap.size - self.hlow_heap.size > 1 : # rebalance heap to keep it balanced high = self.hhigh_heap.extract_min() self.hlow_heap.insert(high) elif self.hlow_heap.size - self.hhigh_heap.size > 1: low = self.hlow_heap.extract_max() self.hhigh_heap.insert(low) def insert_heap(self, i): if self.hlow_heap.is_empty(): low = None else: low = self.hlow_heap.peek_max() if self.hhigh_heap.is_empty(): high = None else: high = self.hhigh_heap.peek_min() if low is None or i < low: self.hlow_heap.insert(i) elif high is not None and i > high: self.hhigh_heap.insert(i) else:# i wedged inbetween insert in first heap by default self.hlow_heap.insert(i) def median(self): if self.hhigh_heap.size - self.hlow_heap.size == 1: return self.hhigh_heap.peek_min() else:# default choice when hlow is bigger/same size as hhigh return self.hlow_heap.peek_max()
g.add_edge(curr, int(j[0]), int(j[1])) minheap = MinHeap() start_vertex = 1 #store shortest distances, by default is infinite length to reach shortest_distance = {start_vertex: 0} added_vertices = [1] curr = start_vertex curr_vertex = g.get_graph()[curr] for neighbour, weight in curr_vertex.get_neighbours().items(): #key is the weight of getting to each vertex in the unexplored area #first vertex in data is the source and second is the destination minheap.insert(weight, curr, neighbour) while not minheap.is_empty(): popped = minheap.pop() curr = popped.get_data()[1] if curr in shortest_distance: #just delete and move on since this vertex has already been seen continue #the vertex from the searched that points to the new element curr_parent = popped.get_data()[0] #add current vertex to shortest distance so the distance has been set shortest_distance[curr] = popped.get_key() for neighbour, weight in g.graph[curr].get_neighbours().items(): #popping from min heap and ignoring those that were seen before, so the shortest paths will keep coming up first, so no need to delete #the check if curr in shortest distance also ensures that our duplicate entries for same vertex will be ignored since they would #have previously been inserted into minheap #for below, new distance to each neighbour from the current would be the shortest distance to current + weight of edge between them