【问题标题】:Finding goal in DepthFirstSearch在 DepthFirstSearch 中寻找目标
【发布时间】:2016-02-29 00:47:17
【问题描述】:

我只是想知道把这段代码放在哪里

if(node == goal){
            System.out.print("Found path: ");
            for(int n : stack){
                System.out.print(n + " ");
            }
        }

在这个方法中:

public void performRecursiveDFS(Graph G, int node, int goal) {
    Stack<Integer> stack = new Stack<Integer>();
    stack.push(node);
    while (!stack.isEmpty()) {
        node = stack.pop();
         if (!visited[node]) {
            visited[node] = true;
            for (int w : G.adjList(node)) {
                stack.push(w);
            }
        }
    }
}

原因是,我想打印从起始节点到目标节点的路径。例如像这样,Found path: 0 1 2 3 4 7。我尝试将它放在node = stack.pop() 之后,但它向我展示了类似Found path: 3 的内容。有什么理由/建议吗?我的代码有问题吗?如果有,请详细指导我。欢迎提问。提前致谢。

【问题讨论】:

    标签: java stack graph-algorithm path-finding depth-first-search


    【解决方案1】:

    您已经实现了跟踪访问节点的 DFS 的一部分,您可以扩展它以了解链接到下一个节点的源路径

    完整的 DFS 实现如下所示,也将处理路径请求

    import java.util.ArrayDeque;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Deque;
    
    
    public class DirectedDFS {
    
        private final Digraph g;
        private final int source;
    
        private boolean[] marked;
        private int[] edgeFrom;
    
        public DirectedDFS(Digraph g, int source) {
            this.g = g;
            this.source = source;
            init(g);
            dfs(g, source);
        }
    
        private void init(Digraph g) {
            this.marked = new boolean[g.V()];
            this.edgeFrom = new int[g.V()];
            Arrays.fill(edgeFrom, -1);
        }
    
        private void dfs(Digraph g, int source) {
    
            marked[source] = true;
            for (int vertex : g.adj(source)) {
                if (!marked[vertex]) {
                    edgeFrom[vertex] = source;
                    dfs(g, vertex);
                }
            }
        }
    
        public boolean hasPath(int v) {
            return marked[v];
        }
    
        public Iterable<Integer> path(int v) {
            if (hasPath(v)) {
                final Deque<Integer> paths = new ArrayDeque<>();
                int vertex = v;
                paths.push(v);
                while ((vertex = edgeFrom[vertex]) != -1) {
                    paths.push(vertex);
                }
                return paths;
            }
            return (Iterable<Integer>) Collections.emptyIterator();
        }
    
    }
    

    【讨论】:

    • 我目前正在使用无向图,其中我有一个文本文件包含一对数字(节点)来显示两个节点之间的连接。这和有向图一样吗?
    • 是的,算法对于两种类型的图表都保持不变。
    • 好的,我会试试这个。谢谢。我会告诉你它是否有效。
    • 你说的我试过了,效果很好。感谢那。不幸的是,我的路径中的问题并不完整。例如,我的目标是从 0 到 1 和这样的路径 "-->0 -->3 -->3 -->0 -->5 -->4 -->5 -->7 -->7 -->8 -->9" 但我有 0 - 11 个顶点。你知道为什么会这样吗?如果这是另一个问题,那么我可以发布另一个与此相关的问题。提前致谢。
    • 是的,我认为您应该就此发表另一个问题
    【解决方案2】:

    堆栈当前正在存储要检查的节点,而不是已经检查到当前点的节点。

    要获取所采用的路径,您需要创建一个列表并将每个选中的节点添加到该列表中。

    获得一个节点后,您可以检查该节点是否是目标节点,然后您可以打印出列表

    【讨论】:

      【解决方案3】:

      您当前没有存储当前节点的路径,因此您无法打印它。实现这一点的一个相当简单的方法是使用地图来绘制返回原点的路径。这可以替代您对visited 数组的使用。

      它的外观如下:

      public void performRecursiveDFS(Graph G, int start, int goal) {
          Stack<Integer> remaining = new Stack<Integer>();
          remaining.push(start);
          Map<Integer, Integer> previous = new HashMap<>();
          while (!remaining .isEmpty()) {
              int current = remaining.pop();
              if (current == goal) {
                  Deque<Integer> path = new LinkedList<>();
                  path.addFirst(current);
                  while (previous.containsKey(path.peek())
                      path.addFirst(previous.get(path.peek()));
                  // print path
              } else if (!previous.containsKey(current)) {
                  for (int w : G.adjList(current)) {
                      previous.put(w, current);
                      remaining.push(w);
                  }
              }
          }
      }
      

      【讨论】:

      • 为简单起见,是否需要 Map?我以前没用过。
      • @MCMadMoefat 不,没有必要 - 您可以随时创建路径列表。
      • 我尝试测试您的代码以了解其工作原理。不知何故,当我将 System.out.print 方法放在“//打印路径”注释下时,它不会打印路径。不知道是不是我做错了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 2015-09-03
      • 1970-01-01
      相关资源
      最近更新 更多