mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Bug 1383880: add Graph.visit_preorder; r=ahal
MozReview-Commit-ID: BWGqLUuWlN9 --HG-- extra : rebase_source : 84321e62d789faa7972ac92486e9831684f7d50d
This commit is contained in:
parent
7e084ff0ae
commit
553b0d0e71
@ -78,16 +78,9 @@ class Graph(object):
|
||||
new_edges = edges | add_edges
|
||||
return Graph(new_nodes, new_edges)
|
||||
|
||||
def visit_postorder(self):
|
||||
"""
|
||||
Generate a sequence of nodes in postorder, such that every node is
|
||||
visited *after* any nodes it links to.
|
||||
|
||||
Behavior is undefined (read: it will hang) if the graph contains a
|
||||
cycle.
|
||||
"""
|
||||
def _visit(self, reverse):
|
||||
queue = collections.deque(sorted(self.nodes))
|
||||
links_by_node = self.links_dict()
|
||||
links_by_node = self.reverse_links_dict() if reverse else self.links_dict()
|
||||
seen = set()
|
||||
while queue:
|
||||
node = queue.popleft()
|
||||
@ -101,6 +94,23 @@ class Graph(object):
|
||||
queue.extend(n for n in links if n not in seen)
|
||||
queue.append(node)
|
||||
|
||||
def visit_postorder(self):
|
||||
"""
|
||||
Generate a sequence of nodes in postorder, such that every node is
|
||||
visited *after* any nodes it links to.
|
||||
|
||||
Behavior is undefined (read: it will hang) if the graph contains a
|
||||
cycle.
|
||||
"""
|
||||
return self._visit(False)
|
||||
|
||||
def visit_preorder(self):
|
||||
"""
|
||||
Like visit_postorder, but in reverse: evrey node is visited *before*
|
||||
any nodes it links to.
|
||||
"""
|
||||
return self._visit(True)
|
||||
|
||||
def links_dict(self):
|
||||
"""
|
||||
Return a dictionary mapping each node to a set of the nodes it links to
|
||||
|
@ -129,6 +129,31 @@ class TestGraph(unittest.TestCase):
|
||||
"postorder visit of a disjoint graph satisfies invariant"
|
||||
self.assert_postorder(self.disjoint.visit_postorder(), self.disjoint.nodes)
|
||||
|
||||
def assert_preorder(self, seq, all_nodes):
|
||||
seen = set()
|
||||
for e in seq:
|
||||
for l, r, n in self.tree.edges:
|
||||
if r == e:
|
||||
self.failUnless(l in seen)
|
||||
seen.add(e)
|
||||
self.assertEqual(seen, all_nodes)
|
||||
|
||||
def test_visit_preorder_tree(self):
|
||||
"preorder visit of a tree satisfies invariant"
|
||||
self.assert_preorder(self.tree.visit_preorder(), self.tree.nodes)
|
||||
|
||||
def test_visit_preorder_diamonds(self):
|
||||
"preorder visit of a graph full of diamonds satisfies invariant"
|
||||
self.assert_preorder(self.diamonds.visit_preorder(), self.diamonds.nodes)
|
||||
|
||||
def test_visit_preorder_multi_edges(self):
|
||||
"preorder visit of a graph with duplicate edges satisfies invariant"
|
||||
self.assert_preorder(self.multi_edges.visit_preorder(), self.multi_edges.nodes)
|
||||
|
||||
def test_visit_preorder_disjoint(self):
|
||||
"preorder visit of a disjoint graph satisfies invariant"
|
||||
self.assert_preorder(self.disjoint.visit_preorder(), self.disjoint.nodes)
|
||||
|
||||
def test_links_dict(self):
|
||||
"link dict for a graph with multiple edges is correct"
|
||||
self.assertEqual(self.multi_edges.links_dict(), {
|
||||
|
Loading…
Reference in New Issue
Block a user