def build_trie(freq):
        min_pq = MinPQ()
        for i in range(256):
            if freq[i]:
                min_pq.insert(chr(i), freq, None, None)

        while min_pq.size() > 1:
            left = min_pq.del_min()
            right = min_pq.del_min()
            parent = Node('\0', left.freq + right.freq, left, right)
            min_pq.insert(parent)
        return min_pq.del_min()
    def build_trie(freq):
        min_pq = MinPQ()
        for i in range(256):
            if freq[i]:
                min_pq.insert(chr(i), freq, None, None)

        while min_pq.size() > 1:
            left = min_pq.del_min()
            right = min_pq.del_min()
            parent = Node('\0', left.freq + right.freq, left, right)
            min_pq.insert(parent)
        return min_pq.del_min()
Ejemplo n.º 3
0
    def del_edge(self, graph, edge):

        if edge not in set(self._mst):
            return self._mst

        # init disjoint set with iterable object
        uf = GenericUnionFind([(e.either(), e.other(e.either()))
                               for e in self._mst if e is not edge])

        pq = MinPQ()
        for e in graph.edges():
            if e is not edge:
                pq.insert(e)

        tmp = Queue([e for e in self._mst if e is not edge])

        # find the minimum edge with both vertices is not connected
        while not pq.is_empty():
            min_edge = pq.del_min()
            vertx_a = min_edge.either()
            vertx_b = min_edge.other(vertx_a)

            if uf.connected(vertx_a, vertx_b):
                continue
            # only need one edge
            tmp.enqueue(min_edge)
            break

        self._mst = tmp
        return self._mst
    def del_edge(self, graph, edge):

        if edge not in set(self._mst):
            return self._mst

        # init disjoint set with iterable object
        uf = GenericUnionFind([(e.either(), e.other(e.either()))
                               for e in self._mst if e is not edge])

        pq = MinPQ()
        for e in graph.edges():
            if e is not edge:
                pq.insert(e)

        tmp = Queue([e for e in self._mst if e is not edge])

        # find the minimum edge with both vertices is not connected
        while not pq.is_empty():
            min_edge = pq.del_min()
            vertx_a = min_edge.either()
            vertx_b = min_edge.other(vertx_a)

            if uf.connected(vertx_a, vertx_b):
                continue
            # only need one edge
            tmp.enqueue(min_edge)
            break

        self._mst = tmp
        return self._mst
class LazyPrimMST(object):

    """
      Lazy version Prim-Minimum-Spanning-Tree. This algorithm is a greedy strategy.
    First input a start vertex, then visit all the adjacent edges, if the other side
    of the vertex is not marked, put the edge into a priority queue. The result queue
    only enqueue those edges with small weight and either vertex is not marked.
    The cost of space is proportional to number of edges, and the worst case of running time
    is proportional to O(ElogE) (E is the number of edges).
    >>> test_data = ((4, 5, 0.35), (4, 7, 0.37), (5, 7, 0.28), (0, 7, 0.16), (1, 5, 0.32),
    ...              (0, 4, 0.38), (2, 3, 0.17), (1, 7, 0.19), (0, 2, 0.26), (1, 2, 0.36),
    ...              (1, 3, 0.29), (2, 7, 0.34), (6, 2, 0.4), (3, 6, 0.52), (6, 0, 0.58),
    ...              (6, 4, 0.93))
    >>> ewg = EdgeWeightedGraph()
    >>> for a, b, weight in test_data:
    ...    edge = Edge(a, b, weight)
    ...    ewg.add_edge(edge)
    ...
    >>> lazy_prim_mst = LazyPrimMST(ewg, 0)
    >>> lazy_prim_mst.weight()
    1.81
    >>> [edge for edge in lazy_prim_mst.edges()]
    [0-7 0.16, 1-7 0.19, 0-2 0.26, 2-3 0.17, 5-7 0.28, 4-5 0.35, 6-2 0.4]
    """

    def __init__(self, graph, start_vertex):
        self._pq = MinPQ()
        self._marked = defaultdict(bool)
        self._mst = Queue()
        self.visit(graph, start_vertex)
        while not self._pq.is_empty():
            edge = self._pq.del_min()
            a = edge.either()
            b = edge.other(a)
            if self._marked[a] and self._marked[b]:
                continue
            self._mst.enqueue(edge)
            if not self._marked[a]:
                self.visit(graph, a)
            if not self._marked[b]:
                self.visit(graph, b)

    def visit(self, graph, vertex):
        self._marked[vertex] = True
        for edge in graph.adjacent_edges(vertex):
            if not self._marked[edge.other(vertex)]:
                self._pq.insert(edge)

    def edges(self):
        return self._mst

    # 4.3.31 practice, lazy weight implementation
    def weight(self):
        return sum(i.weight for i in self._mst)
Ejemplo n.º 6
0
class LazyPrimMST(object):
    """
      Lazy version Prim-Minimum-Spanning-Tree. This algorithm is a greedy strategy.
    First input a start vertex, then visit all the adjacent edges, if the other side
    of the vertex is not marked, put the edge into a priority queue. The result queue
    only enqueue those edges with small weight and either vertex is not marked.
    The cost of space is proportional to number of edges, and the worst case of running time
    is proportional to O(ElogE) (E is the number of edges).
    >>> test_data = ((4, 5, 0.35), (4, 7, 0.37), (5, 7, 0.28), (0, 7, 0.16), (1, 5, 0.32),
    ...              (0, 4, 0.38), (2, 3, 0.17), (1, 7, 0.19), (0, 2, 0.26), (1, 2, 0.36),
    ...              (1, 3, 0.29), (2, 7, 0.34), (6, 2, 0.4), (3, 6, 0.52), (6, 0, 0.58),
    ...              (6, 4, 0.93))
    >>> ewg = EdgeWeightedGraph()
    >>> for a, b, weight in test_data:
    ...    edge = Edge(a, b, weight)
    ...    ewg.add_edge(edge)
    ...
    >>> lazy_prim_mst = LazyPrimMST(ewg, 0)
    >>> lazy_prim_mst.weight()
    1.81
    >>> [edge for edge in lazy_prim_mst.edges()]
    [0-7 0.16, 1-7 0.19, 0-2 0.26, 2-3 0.17, 5-7 0.28, 4-5 0.35, 6-2 0.4]
    """
    def __init__(self, graph, start_vertex):
        self._pq = MinPQ()
        self._marked = defaultdict(bool)
        self._mst = Queue()
        self.visit(graph, start_vertex)
        while not self._pq.is_empty():
            edge = self._pq.del_min()
            a = edge.either()
            b = edge.other(a)
            if self._marked[a] and self._marked[b]:
                continue
            self._mst.enqueue(edge)
            if not self._marked[a]:
                self.visit(graph, a)
            if not self._marked[b]:
                self.visit(graph, b)

    def visit(self, graph, vertex):
        self._marked[vertex] = True
        for edge in graph.adjacent_edges(vertex):
            if not self._marked[edge.other(vertex)]:
                self._pq.insert(edge)

    def edges(self):
        return self._mst

    # 4.3.31 practice, lazy weight implementation
    def weight(self):
        return sum(i.weight for i in self._mst)
class PrimitiveLazyPrimMST(object):

    """
    >>> test_data = ((0.35, 4, 5), (0.37, 4, 7), (0.28, 5, 7), (0.16, 0, 7), (0.32, 1, 5),
    ...              (0.38, 0, 4), (0.17, 2, 3), (0.19, 1, 7), (0.26, 0, 2), (0.36, 1, 2),
    ...              (0.29, 1, 3), (0.34, 2, 7), (0.4, 6, 2), (0.52, 3, 6), (0.58, 6, 0),
    ...              (0.93, 6, 4))
    >>> wg = WeightedGraph()
    >>> for edge in test_data:
    ...     wg.add_edge(edge)
    ...
    >>> primitive_mst = PrimitiveLazyPrimMST(wg, 0)
    >>> [edge for edge in primitive_mst.edges()]
    [(0.16, 0, 7), (0.19, 1, 7), (0.26, 0, 2), (0.17, 2, 3), (0.28, 5, 7), (0.35, 4, 5), (0.4, 6, 2)]
    """

    def __init__(self, graph, start_vertex):
        self._marked = defaultdict(bool)
        self._mst = Queue()
        self.pq = MinPQ()
        self.visit(graph, start_vertex)
        while not self.pq.is_empty():
            edge = self.pq.del_min()
            if self._marked[edge[1]] and self._marked[edge[2]]:
                continue
            self._mst.enqueue(edge)
            if not self._marked[edge[1]]:
                self.visit(graph, edge[1])
            if not self._marked[edge[2]]:
                self.visit(graph, edge[2])

    def visit(self, graph, vertex):
        self._marked[vertex] = True
        for edge in graph.adjacent_edges(vertex):
            if edge[1] == vertex and not self._marked[edge[2]]:
                self.pq.insert(edge)
            elif edge[2] == vertex and not self._marked[edge[1]]:
                self.pq.insert(edge)

    def edges(self):
        return self._mst

    def weight(self):
        return sum(edge[0] for edge in self._mst)
Ejemplo n.º 8
0
class PrimitiveLazyPrimMST(object):
    """
    >>> test_data = ((0.35, 4, 5), (0.37, 4, 7), (0.28, 5, 7), (0.16, 0, 7), (0.32, 1, 5),
    ...              (0.38, 0, 4), (0.17, 2, 3), (0.19, 1, 7), (0.26, 0, 2), (0.36, 1, 2),
    ...              (0.29, 1, 3), (0.34, 2, 7), (0.4, 6, 2), (0.52, 3, 6), (0.58, 6, 0),
    ...              (0.93, 6, 4))
    >>> wg = WeightedGraph()
    >>> for edge in test_data:
    ...     wg.add_edge(edge)
    ...
    >>> primitive_mst = PrimitiveLazyPrimMST(wg, 0)
    >>> [edge for edge in primitive_mst.edges()]
    [(0.16, 0, 7), (0.19, 1, 7), (0.26, 0, 2), (0.17, 2, 3), (0.28, 5, 7), (0.35, 4, 5), (0.4, 6, 2)]
    """
    def __init__(self, graph, start_vertex):
        self._marked = defaultdict(bool)
        self._mst = Queue()
        self.pq = MinPQ()
        self.visit(graph, start_vertex)
        while not self.pq.is_empty():
            edge = self.pq.del_min()
            if self._marked[edge[1]] and self._marked[edge[2]]:
                continue
            self._mst.enqueue(edge)
            if not self._marked[edge[1]]:
                self.visit(graph, edge[1])
            if not self._marked[edge[2]]:
                self.visit(graph, edge[2])

    def visit(self, graph, vertex):
        self._marked[vertex] = True
        for edge in graph.adjacent_edges(vertex):
            if edge[1] == vertex and not self._marked[edge[2]]:
                self.pq.insert(edge)
            elif edge[2] == vertex and not self._marked[edge[1]]:
                self.pq.insert(edge)

    def edges(self):
        return self._mst

    def weight(self):
        return sum(edge[0] for edge in self._mst)