versión iterativa de post-fin gráfico de recorrido en java

hck007:

Busco a una versión iterativa del recorrido del grafo posterioridad a la orden java. He escrito el código para hacer DFS iterativos. ¿Cómo podría modificar el código para que el código siguiente se puede imprimir el camino de la post-fin iterativo DFS recorrido? Por ejemplo, la salida del siguiente gráfico debe ser FCBEDA (G).

imagen gráfica

public void DFS(int sourceVertex) {
     Stack<Integer> stack = new Stack<>();
     stack.push(sourceVertex);
     while (!stack.isEmpty()) {
          int v = stack.pop();
          if (!marked[v]) {
               marked[v] = true;
               for (int w : v.adj) {
                    stack.push(w);
               }
          }
     }
}
josejuan:

Su gráfico es un grafo dirigido, no se puede ir de Fa cualquier otro nodo a continuación, DFS de Fretorno sólo el Fnodo. En general, la salida es diferente cuando se utiliza diferente nodo de partida (y si el gráfico está dirigida o no).

Iterativo DFS algoritmo podría ser escrito como:

static List<Node> DFS(Node n) {

    Stack<Node> current = new Stack<>();
    Set<Node> visited = new HashSet<>(); // efficient lookup
    List<Node> result = new ArrayList<>(); // ordered

    current.push(n);

    while(!current.isEmpty()) {
        Node c = current.pop();
        if(!visited.contains(c)) {
            result.add(c);
            visited.add(c);
            // push in reversed order
            IntStream.range(0, c.getChildren().size())
                    .forEach(i -> current.push(c.getChildren().get(c.getChildren().size() - i - 1)));
        }
    }

    return result;
}

Se podría evitar el visited Setsino que lo utiliza resultpara comprobar si un nodo fue visitado toma O(n)momento en que Settoma O(1)(amortizado).

Un ejemplo completo:

public static void main(String[] args) {

    Node A = new Node("A");
    Node B = new Node("B");
    Node C = new Node("C");
    Node D = new Node("D");
    Node E = new Node("E");
    Node F = new Node("F");
    Node G = new Node("G");

    A.getChildren().addAll(asList(B, D));
    B.getChildren().addAll(asList(C));
    C.getChildren().addAll(asList(F));
    D.getChildren().addAll(asList(B, F, E));
    E.getChildren().addAll(asList(F));
    //F.getChildren().addAll(asList());
    G.getChildren().addAll(asList(F));

    testDFS(F);
    testDFS(G);
    testDFS(A);

}

static class Node {
    private final String label;
    private final List<Node> children;

    Node(String label) {
        this.label = label;
        this.children = new ArrayList<>();
    }

    public String getLabel() {
        return label;
    }

    public List<Node> getChildren() {
        return children;
    }

    @Override
    public int hashCode() {
        return getLabel().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Node))
            return false;
        return getLabel().equals(((Node) obj).getLabel());
    }
}

Con salida:

From 'F': F
From 'G': G, F
From 'A': A, B, C, F, D, E

Si desea orden posterior (mostrar primero el último nodo visitado) revertir la lista de resultados (o agregar a la cabeza, etc.).

Para invertir el childrenorden no invierta antes de insertar:

static List<Node> DFSreversedPostOrder(Node n) {

    Stack<Node> current = new Stack<>();
    Set<Node> visited = new HashSet<>(); // efficient lookup
    List<Node> result = new ArrayList<>(); // ordered

    current.push(n);

    while(!current.isEmpty()) {
        Node c = current.pop();
        if(!visited.contains(c)) {
            result.add(0, c);
            visited.add(c);
            c.getChildren().forEach(current::push);
        }
    }

    return result;
}

Ahora, se obtiene CBFEDA:

From 'F': F
From 'G': F, G
From 'A': C, B, F, E, D, A

NOTA que está mal ejemplo ya que después de Enodo que debe visitar Fno B.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=231288&siteId=1
Recomendado
Clasificación