2013-02-16 4 views
9

Можно ли использовать логику первого поиска Breadth для создания топологического типа DAG? Решение в Cormen использует первый поиск глубины, но было бы проще использовать BFS?Топологический поиск и первый поиск по ширине

Причина: BFS посещает все узлы определенной глубины перед посещением узлов со следующим значением глубины. Это, естественно, означает, что родители будут перечислены перед детьми, если мы сделаем BFS. Разве это не то, что нам нужно для топологической сортировки?

+0

Да, это можно сделать. https://www.quora.com/Can-topological-sorting-be-done-using-BFS –

ответ

3

В BFS все края, которые вы на самом деле гуляете, окажутся в правильном направлении. Но все ребра, которые вы не ходите (между узлами на одной глубине или с более глубокими узлами, поддерживающими до более ранних узлов) закончится тем, что вы ошибетесь, если вы разместите график в порядке BFS.

Да, для этого вам действительно нужна DFS.

+1

Посмотрите на это: https://www.quora.com/Can-topological-sorting-be-done- используя-BFS –

5

Возможно, даже википедия describes an algorithm based on BFS.

В основном вы используете очередь, в которую вы вставляете все узлы без входящих ребер. Затем, когда вы извлекаете узел, вы удаляете все его исходящие ребра и вставляете узлы, доступные из него, которые не имеют других входящих краев.

6

А просто BFS достаточно только для дерева (или леса деревьев), потому что в (лес) деревьев, в-градусы больше 1. Теперь посмотрим на этот случай:

B → C → D 
     ↗ 
    A 

BFS, где очередь инициализируется до A B (чьи числа в градусах равны нулю) вернет A B D C, который не является топологически отсортированным. Вот почему вы должны поддерживать подсчет в градусах и выбирать только узлы, счет которых упал до нуля. (*)

BTW, это недостаток вашей «причины»: BFS только гарантирует, что один из родителей был посещен раньше, а не все из них.

Edit: (*) Другими словами, вы отодвигают соседние узлы которых в-степени равна нулю (в Exemple, после обработки A, D будет пропущена). Итак, вы все еще используете очередь, и вы только что добавили шаг фильтрации к общему алгоритму. При этом, продолжая называть это BFS, вызывает сомнение.

0

Да, вы можете сделать топологическую сортировку, используя BFS. На самом деле я вспомнил, как только мой учитель сказал мне, что если проблема может быть решена BFS, никогда не решите ее решить DFS. Поскольку логика для BFS проще, чем DFS, большую часть времени вы всегда будете нуждаться в прямом решении проблемы.

Как YvesgereY и IVlad отметили, что вам нужно начать с узлами которого полустепень заход является , то есть никакие другие узлы не непосредственно к ним. Обязательно сначала добавьте эти узлы к вашему результату. Вы можете использовать HashMap для сопоставления каждого узла с его неопределенностью и очереди, которая очень часто встречается в BFS, чтобы помочь вашему обходу. Когда вы проводите опрос узла из очереди, его соседям нужно уменьшить на 1, это как удалить узел из графика и удалить границу между узлом и его соседями. Каждый раз, когда вы сталкиваетесь с узлами с индексом 0, предложите их очереди для проверки своих соседей позже и добавьте их в результат.

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; 
} 
Смежные вопросы