/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tsort.py

tsort.topo_sort: new algorithm, improving performance

Instead of using TopoSorter in topo_sort, a different algorithm is used which
is faster for generating the whole sorted list.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
    their children.
35
35
 
36
36
    node identifiers can be any hashable object, and are typically strings.
 
37
 
 
38
    This function has the same purpose as the TopoSorter class, but uses a
 
39
    different algorithm to sort the graph. That means that while both return a list
 
40
    with parents before their child nodes, the exact ordering can be different.
 
41
 
 
42
    topo_sort is faster when the whole list is needed, while when iterating over a
 
43
    part of the list, TopoSorter.iter_topo_order should be used.
37
44
    """
38
 
    return TopoSorter(graph).sorted()
 
45
    # store a dict of the graph.
 
46
    graph = dict(graph)
 
47
    # this is the stack storing on which the sorted nodes are pushed.
 
48
    node_name_stack = []
 
49
 
 
50
    # count the number of children for every node in the graph
 
51
    nchildren = dict.fromkeys(graph.iterkeys(), 0)
 
52
    for parents in graph.itervalues():
 
53
        for parent in parents:
 
54
            if parent in nchildren:
 
55
                nchildren[parent] += 1
 
56
    # keep track of nodes without children in a separate list
 
57
    nochildnodes = [node for (node, n) in nchildren.iteritems() if n == 0]
 
58
 
 
59
    while nochildnodes:
 
60
        # pick a node without a child and add it to the stack.
 
61
        node_name = nochildnodes.pop()
 
62
        node_name_stack.append(node_name)
 
63
 
 
64
        # the parents of the node lose it as a child; if it was the last
 
65
        # child, add the parent to the list of childless nodes.
 
66
        parents = graph.pop(node_name)
 
67
        for parent in parents:
 
68
            if parent in nchildren:
 
69
                nchildren[parent] -= 1
 
70
                if nchildren[parent] == 0:
 
71
                    nochildnodes.append(parent)
 
72
 
 
73
    # if there are still nodes left in the graph,
 
74
    # that means that there is a cycle
 
75
    if graph:
 
76
        raise errors.GraphCycleError(graph)
 
77
 
 
78
    # the nodes where pushed on the stack child first, so this list needs to be
 
79
    # reversed before returning it.
 
80
    node_name_stack.reverse()
 
81
    return node_name_stack
39
82
 
40
83
 
41
84
class TopoSorter(object):