예제 #1
0
def dijkstra(graph=None, source_node=1):
        """ Return shortest path lengths computed by Dijkstra's algorithm. """
        if graph is None:
            return None

        shortest_path_lengths = {}  #dict for keeping track of shortest path legnths

        # min heap to keep track of crossing cuts
        crossing_cuts = Heap([(float("inf"), int(node)) for node in graph.nodes()])
        crossing_cuts.update_key(source_node, 0)

        # main algorithm body
        while crossing_cuts:
            # get smallest crossing cut cut
            shortest_cut = crossing_cuts.pop()
            head_node, path_length = shortest_cut.name, shortest_cut.key
            shortest_path_lengths[head_node] = path_length
            # update heap
            unadded_tail_nodes = set(graph[head_node]) - set(shortest_path_lengths)
            for tail_node in unadded_tail_nodes:
                old_key = crossing_cuts[tail_node].key
                new_key = shortest_path_lengths[head_node] + graph[head_node][tail_node]
                if new_key < old_key:
                    crossing_cuts.update_key(tail_node, new_key)

        return shortest_path_lengths
예제 #2
0
def prim(graph):
    """
    Implements Prim's Minimum Spanning Tree Algorithm in O(VlogE) time with a min heap.
    """
    mst = defaultdict(dict)
    initial_node = random.choice(graph.keys())

    # Initialize minimum heap to contain the nodes of the graph, whose keys
    # are the edge values
    crossing_cuts = Heap([((float("inf"), float("inf")), int(node))
                          for node in graph.keys() if node != initial_node])

    # Populate min heap with initial node's crossing cuts
    for node_name in graph[initial_node].keys():
        new_key = (graph[initial_node][node_name], initial_node)
        crossing_cuts.update_key(node_name, new_key)

    # Pop nodes from minimum heap until minimum spanning tree is formed
    while crossing_cuts:
        smallest_node = crossing_cuts.pop()
        (node_out, (weight, node_in)) = smallest_node.name, smallest_node.key
        mst[node_in][node_out] = weight
        mst[node_out][node_in] = weight

        for node_name in (set(graph[node_out].keys()) - set(mst.keys())):
            new_key = (graph[node_out][node_name], node_out)
            if node_name in crossing_cuts.node_names():
                old_key = crossing_cuts[node_name].key
                if new_key[0] < old_key[0]:
                    crossing_cuts.update_key(node_name, new_key)

    return mst