def Dijkstra_algorithm(graph: Graph, starting_node: int) -> DijkstraAlgorithmResult: dist = [INFINITY for _ in range(graph.nodes_count)] prev = [None for _ in range(graph.nodes_count)] dist[starting_node] = 0 prev[starting_node] = starting_node # prepare list of tuples of nodes labels with their starting distances dist_nodes = [ PQNode(key=i, priority=dist[i]) for i in range(0, graph.nodes_count) ] Q = PriorityQueue(raw=dist_nodes) while not Q.is_empty: # pick the closest node fst = Q.pop().key for e in graph.get_neighbourhood(fst): # scan the neighbourhood snd = e.snd weight = e.weight if dist[snd] > dist[fst] + weight: # update if better route found dist[snd] = dist[fst] + weight prev[snd] = fst Q.bottom_bound_flatten_priority(snd, dist[snd]) return DijkstraAlgorithmResult(dist=dist, prev=prev)
def Prim(graph: Graph) -> Iterable[GraphEdge]: """Returns a MST using Prim's algorithm. """ cost = [INFINITY for _ in range(graph.nodes_count)] prev = [None for _ in range(graph.nodes_count)] # take the first node as the starting node starting_node = 0 cost[starting_node] = 0 prev[starting_node] = starting_node # build a priority queue cost_nodes = [ PQNode(key=i, priority=cost[i]) for i in range(0, graph.nodes_count) ] Q = PriorityQueue(raw=cost_nodes) while not Q.is_empty: fst = Q.pop().key for e in graph.get_neighbourhood(fst): snd = e.snd weight = graph.get_edge_weight(fst, snd, twoway=True) if cost[snd] > weight: cost[snd] = weight prev[snd] = fst Q.bottom_bound_flatten_priority(snd, cost[snd]) # render out actual graph edges using the `prev` list mst = [] for node in range(0, graph.nodes_count): if node == starting_node: continue mst.append( GraphEdge(prev[node], node, graph.get_edge_weight(prev[node], node, twoway=True))) return mst