Beispiel #1
0
def prim(graph):
    """
    Prim's algorithm is a greedy algorithm for the computation of the
    Minimum Spanning Tree (MST).
    The algorithm assumes a graph implemented as incidence list.
    This implementation leverages the BinaryTree and PriorityQueue data
    structures.
    ---
    Time Complexity: O(|E|*log(|V|)
    Memory Complexity: O(|E|)

    :param graph: the graph.
    :return the MST, represented as a tree.
    """
    # initialize the root
    root = 0

    # initialize the tree
    tree = Tree(TreeNode(root))  # MST as a tree
    mst_nodes = {root}  # nodes added to MST

    # initialize weights
    current_weight = len(graph.nodes) * [INFINITE]
    current_weight[root] = 0
    mst_weight = 0

    # initialize the frontier (priority-queue)
    pq = PriorityQueue()
    pq.insert((root, Edge(root, root, 0)), 0)

    # while the frontier is not empty ...
    while not pq.isEmpty():
        # pop from the priority queue the node u with the minimum weight
        pq_elem = pq.popMin()
        node = pq_elem[0]
        # if node u not yet in MST, update the tree
        if node not in mst_nodes:
            edge = pq_elem[1]
            tree_node = TreeNode(node)
            tree_father = tree.foundNodeByElem(edge.tail)
            tree_father.sons.append(tree_node)
            tree_node.father = tree_father
            mst_nodes.add(node)
            mst_weight += edge.weight

        # for every edge (u,v) ...
        curr = graph.inc[node].getFirstRecord()
        while curr is not None:
            edge = curr.elem  # the edge
            head = edge.head  # the head node of the edge
            # if node v not yet added into the tree, push it into the priority
            # queue and apply the relaxation step
            if head not in mst_nodes:
                weight = edge.weight
                pq.insert((head, edge), weight)
                # relaxation step
                if current_weight[head] > weight:
                    current_weight[head] = weight
            curr = curr.next

    return mst_weight, tree
def Dijkstra(graph, root):
    """
    Dijkstra's algorithm for the computation of the shortest path.
    The algorithm assumes a graph implemented as incidence list.
    This implementation leverages the BinaryTree and PriorityQueue data
    structures.
    ---
    Time Complexity: O(|E|*log(|V|))
    Memory Complexity: O()

    :param graph: the graph.
    :param root: the root node to start from.
    :return: the shortest path.
    """
    n = len(graph.nodes)

    # initialize weights:
    # d[i] = inf for every i in E
    # d[i] = 0, if i == root
    currentWeight = n * [INFINITE]
    currentWeight[root] = 0

    # initialize the tree
    tree = Tree(TreeNode(root))
    mstNodes = {root}
    mstWeight = 0

    # initialize the frontier (priority queue)
    pq = PriorityQueue()
    pq.insert((root, Edge(root, root, 0)), 0)

    # while the frontier is not empty ...
    while not pq.isEmpty():
        # pop from the priority queue the node u with the minimum weight
        pq_elem = pq.popMin()
        node = pq_elem[0]
        # if node not yet in the tree, update the tree
        if node not in mstNodes:
            edge = pq_elem[1]
            treeNode = TreeNode(node)
            father = tree.foundNodeByElem(edge.tail)
            father.sons.append(treeNode)
            treeNode.father = father
            mstNodes.add(node)
            mstWeight += edge.weight

        # for every edge (u,v) ...
        curr = graph.inc[node].getFirstRecord()
        while curr is not None:
            edge = curr.elem  # the edge
            head = edge.head  # the head node of the edge
            # if node v not yet added into the tree, push it into the priority
            # queue and apply the relaxation step
            if head not in mstNodes:
                tail = edge.tail
                weight = edge.weight
                currWeight = currentWeight[head]
                distTail = currentWeight[tail]
                pq.insert((head, edge), distTail + weight)
                # relaxation step
                if currWeight == INFINITE:
                    currentWeight[head] = distTail + weight
                elif distTail + weight < currWeight:
                    currentWeight[head] = distTail + weight
            curr = curr.next

    return currentWeight