Java深度优先递归函数

时间:2013-03-11 20:36:07

标签: java recursion graph-theory

我在Java中使用递归函数(图论)来获取4x4表中的所有路径,从随机起点开始。可能的方向是水平,垂直和对角线,但我要求相同的位置不能访问两次。

到目前为止,脚本运行正常,我得到了很多组合。问题是在函数的for循环中,当有多种可能的方法时,我在第二个和后面的循环中得到错误的结果,因为boolean [] tempvisited没有回到他的旧值。

我希望有人能够理解我的英语和我的问题。到目前为止,这是我的代码:

// here I define a constant input of values:
String letters = "1548987425461854"

// This matrix shows all possible directions from every startpoint in the matrix:
// from the second value, you may get to the following locations: 1,3,5,6 and 7
    private int[][] matrix = {
        {1,4,5},
        {0,2,4,5,6},
        {1,3,5,6,7},
        {2,6,7},
        {0,1,5,8,9},
        {0,1,2,4,6,8,9,10},
        {1,2,3,5,7,9,10,11},
        {2,3,6,10,11},
        {4,5,9,12,13},
        {4,5,6,8,10,12,13,14},
        {5,6,7,9,11,13,14,15},
        {6,7,10,14,15},
        {8,9,13},
        {8,9,10,12,14},
        {9,10,11,13,15},
        {10,11,14}
};

// Here begins the recursive function 
public List<Combination> depthFirst(int vertex, boolean[] visited, Combination zeichen, List<Combination> combis){
  // A temporary list of booleans to mark every value position visited or not
  boolean[] tempvisited = new boolean[16];

  // combis is the whole list of ways, zeichen is just the actual combination
  zeichen.name = zeichen.name + this.letters.charAt(vertex);
  combis.add(zeichen.name);

    //marks actual value as visited
    visited[vertex] = true;
    for(int i = 0; i < 16; i++){
        tempvisited[i] = visited[i];
    }//end for

    // going to next possible locations
    for (int i = 0; i < this.matrix[vertex].length; i++) {
        if (!visited[this.matrix[vertex][i]]) {         
            combis = depthFirst(this.matrix[vertex][i], tempvisited, zeichen, combis);      
        }//end if
    }//end for
    return combis;
}

4 个答案:

答案 0 :(得分:0)

您对tempvisited有正确的想法,并制作副本。但是你在错误的地方这样做了。

您正在设置visited[vertex] = true,这意味着您传入的visited正在发生变化。你想要的是visited永远不会改变。复制一份,然后对该副本进行更改。

另外,我注意到你每次都使用相同的zeichen。因此,如果您有一个3步长的路径,则您的combis列表将包含相同zeichen的3个副本。这似乎不正确。

答案 1 :(得分:0)

在第一个for循环之前,将visited [vertex]设置为true;您可以在返回之前将其重置为false。如果每次调用都撤消它所做的更改(直接),那么每次调用都将返回,并在调用时返回到其状态。没有必要的温度。

答案 2 :(得分:0)

深入了解深度优先搜索(DFS)的其他递归解决方案(伪代码)。

void search(Node root) {
 if (root == null) return;

 visit(root);
 root.visited = true;
 foreach (Node n in root.adjacent) {
  if (n.visited == false)
   search(n);
 }
}

答案 3 :(得分:0)

实际上,您不需要访问数组的副本。在深度查询的reccurrent调用之前将节点标记为已访问,然后在调用之后立即“取消标记”它。类似的东西:

for (int i = 0; i < this.matrix[vertex].length; i++) {
    if (!visited[this.matrix[vertex][i]]) {     
        visited[this.matrix[vertex][i]] = true;  
        combis = depthFirst(this.matrix[vertex][i], tempvisited, zeichen, combis);      
        visited[this.matrix[vertex][i]] = false;
    }//end if
}//end for