Search code examples
pythongraphnetworkxgraph-algorithmdepth-first-search

Is there a specific name for this depth-first-search variant?


I use the algorithm below to traverse a (networkx) graph in a specific order. It is similar to a classic depth-first search with the difference that the deeper nodes are retrieved before their parent nodes. Out of curiosity: would there be any specific name to refer to this behaviour?

>>> import networkx

>>> def traverse_graph_dfs_like(graph, source):
...     """Yield nodes from graph beginning with the lowest left"""

...     stack = []
...     stack.append(source)
...     child_generators = {source: graph.neighbors(source)}

...     while stack:
...         try:
...             first_child = next(child_generators[stack[-1]])
...         except StopIteration:
...             yield stack.pop()
...         else:
...             stack.append(first_child)
...             child_generators[first_child] =  graph.neighbors(first_child)

>>> g = networkx.DiGraph({0: [1, 2], 1: [3, 4], 2: [5, 6]})

>>> list(traverse_graph_dfs_like(g, 0))
[3, 4, 1, 5, 6, 2, 0]


>>> list(networkx.algorithms.dfs_tree(g, 0))
[0, 1, 3, 4, 2, 5, 6]

Solution

  • You want to visit nodes with depth-first-search post-order. In this method, you traverse subtrees from left to right by recursively calling the post-order function. Once you have traversed them all, you access the data part of the current node. There are other ways to traverse a tree (for example, pre-order, in-order, reverse in-order, etc.). For more info you can refer to this Wikipedia page.

    NetworkX does provide an implementation of this algorithm: networkx.algorithms.traversal.depth_first_search.dfs_postorder_nodes. Specifically, it is a generator of nodes in a depth-first-search pre-ordering. Here's how you can use it:

    from networkx import DiGraph
    from networkx.algorithms.traversal.depth_first_search import dfs_postorder_nodes
    
    g = DiGraph({0: [1, 2], 1: [3, 4], 2: [5, 6]})
    print(*dfs_postorder_nodes(g, source=0))
    

    The printed output is exactly what you are looking for: 3 4 1 5 6 2 0.