深度优先/广度优先算法打印所有节点;如何让它只打印路径中的节点?

时间:2015-07-06 10:29:02

标签: java algorithm nodes depth-first-search adjacency-matrix

我有以下表格的邻接矩阵adj

0 0 0 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 
0 0 0 0 0 1 0 0 0 
1 0 0 0 1 0 1 0 0 
0 0 0 1 0 1 0 0 0 
0 0 1 0 1 0 0 0 1 
0 0 0 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 
0 0 0 0 0 1 0 0 0 

这是具有规则adj(x,y) = 1的迷宫的邻接矩阵,如果:

  1. x!= y
  2. x与y
  3. 相邻
  4. x或y都不是迷宫中的墙
  5. 迷宫如下(旁边是元素编号):

    S X E | 1 2 3
    O O O | 4 5 6
    O X O | 7 8 9
    //S = starting position
    //E = ending position
    //X = wall
    

    我有一个DFS算法,它会显示要从S遍历到E的节点,但它会显示不必要的节点。

    public static void main(String [] args){
        int[][] adj = //the adjacency matrix
        boolean[] visited = new boolean[adj.length];
        int n = adj.length;    
        int m = 1; //starting position
        int o = 3; //ending position
        DFS(adjMatrix, visited, n, m, o);
    }
    
    public static void DFS(int[][] adj, boolean[] visited, int n, int i, int o){
        System.out.print(" " + (i+1));
        visited[i]= true;
        if (i+1 != o) {
            for (int j = 0; j<n;j++){
                if(!(visited[j]) && adj[i][j]==1){
                   DFS(adj, visited, n, j, o);
                }
            }
        }
    }
    
    public static void BFS(int[][] adj, boolean[] visited, int n, int i, int o){
        queue Q = new queue;
        visited[i]= true;
        Q.enqueue(i);
        while (!Q.isEmpty()) {
            //...
        }
    }
    

    这会打印1 4 5 6 3 9 7。我一直在修改它,以便只打印1 4 5 6 3

    我在这里做错了什么?

3 个答案:

答案 0 :(得分:4)

除了DFS算法所需的修复之外,代码还存在一些主要问题:

  • 你开始和结束是错误的:它应该减少1(因为 指数是0基础)
  • 您的adjanecy矩阵是错误的(它的大小为@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView (R.layour.activity_main); } - 它应该是一个平方矩阵)(编辑固定它)
  • 您的解决方案应该只打印路径中的元素。一种方法是返回10X9(而不是List<> - 填充当前路径中的所有节点。如果到达目的地,则创建列表,否则 - 返回{{1仅当递归调用返回的内容不是void时附加元素。附加代码

另请注意,它以正确的顺序打印节点(而不是颠倒顺序)

null

将导致(如预期):

null

作为旁注,尽管此解决方案完成(总是会找到解决方案,如果存在),但它不是最佳 - 它可能会返回比最短的一个。

如果您想找到从源到目标的最短路径,请考虑切换到BFS

答案 1 :(得分:1)

尝试使用此代码:

public static boolean DFS(int[][] adj, boolean[] visited, int n, int i, int o){        
    visited[i]= true;
    boolean good = false;
    if (i+1 != o) {
        for (int j = 0; j<n;j++){
            if(!(visited[j]) && adj[i][j]==1){
               good |= DFS(adj, visited, n, j, o);
            }
        }
    } else {
        good = true;
    }
    if (good) System.out.print(" " + (i+1));
    return good;
}

这将反向打印路径(从头到尾) - 但它只会打印属于良好路径的节点。如果需要以开始 - 结束顺序打印路径,可以将其存储在数组中,然后反向打印:

public static void DFS(int[][] adj, boolean[] visited, 
       ArrayList<int> path, int n, int i, int o){        
    visited[i]= true;
    if (i+1 != o) {
        for (int j = 0; j<n;j++){
            if(!(visited[j]) && adj[i][j]==1){
               path.add(j);
               DFS(adj, visited, n, j, o);
               path.remove(path.size()-1);
            }
        }
    } else {
        // show path
        for (int i : path) {
            System.out.print(" " + i);
        }
    }        
}

答案 2 :(得分:1)

当您最终到达目的地时,方法堆栈将具有路径。

  ArrayList<Integer> list = new ArrayList<>(); // this will have your path.
  public static boolean DFS(int[][] adj, boolean[] visited, int n, int i, int o){
    if(i==o){
       list.add(o);
      //System.out.println(i);
      return true;
    }
    visited[i]= true;
    for (int j = 0; j<n;j++){
       if(!(visited[j]) && adj[i][j]==1){
          if(DFS(adj, visited, n, j, o)){
              list.add(0,j);
              //System.out.println(j);
              return true;
           }
         }
     }
   return false;
  }