13

Is it possible to use Breadth first search logic to do a topological sort of a DAG? The solution in Cormen makes use of Depth first search but wouldn't be easier to use BFS?

Reason: BFS visits all the nodes in a particular depth before visiting nodes with the next depth value. It naturally means that the parents will be listed before the children if we do a BFS. Isn't this exactly what we need for a topological sort?

Karthik N
  • 131
  • 1
  • 5
  • Yes , it can be done. https://www.quora.com/Can-topological-sorting-be-done-using-BFS – Number945 Dec 19 '15 at 14:17
  • Related posts - [Using BFS for topological sort](https://stackoverflow.com/q/25229624/465053), [Topological order using bfs](https://stackoverflow.com/q/30869987/465053) , & [Relationship between BFS and topological sort](https://stackoverflow.com/q/12373495/465053) – RBT Jul 13 '18 at 00:10

4 Answers4

9

A mere BFS is only sufficient for a tree (or forest of trees), because in (forest of) trees, in-degrees are at most 1. Now, look at this case:

B → C → D
      ↗
    A

A BFS where queue is initialized to A B (whose in-degrees are zero) will return A B D C, which is not topologically sorted. That's why you have to maintain in-degrees count, and only pick nodes whose count has dropped to zero. (*)

BTW, this is the flaw of your 'reason' : BFS only guarantee one parent has been visited before, not all of them.

Edit: (*) In other words you push back adjacent nodes whose in-degree is zero (in the exemple, after processing A, D would be skipped). So, you're still using a queue and you've just added a filtering step to the general algorithm. That being said, continuing to call it a BFS is questionable.

YvesgereY
  • 3,778
  • 1
  • 20
  • 19
4

It is possible, even wikipedia describes an algorithm based on BFS.

Basically, you use a queue in which you insert all nodes with no incoming edges. Then, when you extract a node, you remove all of its outgoing edges and insert the nodes reachable from it that have no other incoming edges.

IVlad
  • 43,099
  • 13
  • 111
  • 179
3

In a BFS all of the edges you actually walk will end up in the correct direction. But all the edges you don't walk (those between nodes at the same depth, or those from deeper nodes back up to earlier nodes) will end up going the wrong way if you lay out the graph in BFS order.

Yes, you really need DFS to do it.

Keith Randall
  • 22,985
  • 2
  • 35
  • 54
0

Yes, you can do topological sorting using BFS. Actually I remembered once my teacher told me that if the problem can be solved by BFS, never choose to solve it by DFS. Because the logic for BFS is simpler than DFS, most of the time you will always want a straightforward solution to a problem.

As YvesgereY and IVlad has mentioned, you need to start with nodes of which the indegree is 0, meaning no other nodes direct to them. Be sure to add these nodes to your result first.You can use a HashMap to map every node with its indegree, and a queue which is very commonly seen in BFS to assist your traversal. When you poll a node from the queue, the indegree of its neighbors need to be decreased by 1, this is like delete the node from the graph and delete the edge between the node and its neighbors. Every time you come across nodes with 0 indegree, offer them to the queue for checking their neighbors later and add them to the result.

public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {

    ArrayList<DirectedGraphNode> result = new ArrayList<>();
    if (graph == null || graph.size() == 0) {
        return result;
    }
    Map<DirectedGraphNode, Integer> indegree = new HashMap<DirectedGraphNode, Integer>();
    Queue<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>();

    //mapping node to its indegree to the HashMap, however these nodes
    //have to be directed to by one other node, nodes whose indegree == 0
    //would not be mapped.
    for (DirectedGraphNode DAGNode : graph){
        for (DirectedGraphNode nei : DAGNode.neighbors){
            if(indegree.containsKey(nei)){
                indegree.put(nei, indegree.get(nei) + 1);
            } else {
                indegree.put(nei, 1);
            }
        }
    }


    //find all nodes with indegree == 0. They should be at starting positon in the result
    for (DirectedGraphNode GraphNode : graph) {
        if (!indegree.containsKey(GraphNode)){
            queue.offer(GraphNode);
            result.add(GraphNode);
        }
    }


    //everytime we poll out a node from the queue, it means we delete it from the 
    //graph, we will minus its neighbors indegree by one, this is the same meaning 
    //as we delete the edge from the node to its neighbors.
    while (!queue.isEmpty()) {
        DirectedGraphNode temp = queue.poll();
        for (DirectedGraphNode neighbor : temp.neighbors){
            indegree.put(neighbor, indegree.get(neighbor) - 1);
            if (indegree.get(neighbor) == 0){
                result.add(neighbor);
                queue.offer(neighbor);
            }
        }
    }
    return result;
}
Caiwei Wu
  • 361
  • 1
  • 3
  • 6