深度优先搜索多个解决方案

时间:2015-12-26 21:47:23

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

我有这个迷宫,代表无向图。 这是它的样子:

ng-options="product as product.name for product in vm.filtered_products | filter : { isExtinguisher : vm.isExtinguisher, brand : vm.current_brand } : true"

在此图中,使用深度优先搜索,它显示了从起始节点到目标节点的解决方案。我作为起始节点的输入是11 3 2 3 0 3 1 4 5 4 5 7 6 7 7 8 8 9 9 10 6 11 7 11 ,我的目标节点是0。我作为目标路径获得的解决方案是1,但如果再次分析,还有另一个解决方案0-3-11-7-5-4-1。我的目的不是展示最佳解决方案,而是展示他们有多少解决方案,并在以后分析最佳解决方案。

我遇到的困难是我无法打印多个解决方案。它只打印0-3-11-6-7-5-4-1没有其他内容,有时只打印0-3-11-7-5-4-1因为我预计会有两个要打印。这是我到目前为止所做的代码:

0-3-11-6-7-5-4-1

MazeGraph源代码:

public class DepthFirstSearch {

    private final boolean[] visited;
    private final int sourceNode;
    private final int[] pathTo;

    /**
     *
     * @param mazeGraph
     * @param sourceNode
     * @param goal
     */
    public DepthFirstSearch(MazeGraph mazeGraph, int sourceNode, int goal) {
        this.sourceNode = sourceNode;
        visited = new boolean[mazeGraph.node];
        pathTo = new int[mazeGraph.node];
        performRecursiveDFS(mazeGraph, sourceNode, goal);
    }

    //Perform recursive depth-first search
    private void performRecursiveDFS(MazeGraph mazeGraph, int node, int goal) {
        visited[node] = true;
        for (int arc : mazeGraph.getAdjacencyList(node)) {
            if (!visited[arc]) {

                pathTo[arc] = node;
                performRecursiveDFS(mazeGraph, arc, goal);

            }
        }
    }

    //Put path to goal in the stack
    public Stack<Integer> pathTo(int toGoalNode) {
        if (!visited[toGoalNode]) {
            return null;
        }
        Stack<Integer> pathStack = new Stack<Integer>();
        for (int pathToGoalNode = toGoalNode; pathToGoalNode != sourceNode; pathToGoalNode = pathTo[pathToGoalNode]) {
            pathStack.push(pathToGoalNode);
        }
        pathStack.push(sourceNode);
        reverseStack(pathStack);
        return pathStack;
    }

    //Reverse the stack
    public void reverseStack(Stack<Integer> stackToBeReverse) {

        if (stackToBeReverse.isEmpty()) {
            return;
        }

        int bottom = popBottomStack(stackToBeReverse);
        reverseStack(stackToBeReverse);
        stackToBeReverse.push(bottom);
    }

    //Pop the bottom of the stack
    private int popBottomStack(Stack<Integer> stackToBeReverse) {
        int popTopStack = stackToBeReverse.pop();
        if (stackToBeReverse.isEmpty()) {
            return popTopStack;
        } else {
            int bottomStack = popBottomStack(stackToBeReverse);
            stackToBeReverse.push(popTopStack);
            return bottomStack;
        }
    }

    //Print the path to goal
    public void printPath( int toGoal) {

        if (visited[toGoal]) {
            out.println("Path to Goal: ");
            for (int x : pathTo(toGoal)) {
                if (x == toGoal) {
                    out.print(x);
                } else {
                    out.print(x + " - ");
                }
            }
            out.println();
        }
    }

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        Scanner scanFile = new Scanner(in);
        out.print("Enter maze file: ");
        String file = scanFile.nextLine();
        out.print("Enter start node: ");
        int startNode = scanFile.nextInt();
        out.print("Enter goal node: ");
        int goalNode = scanFile.nextInt();
        MazeGraph mazeGraph = new MazeGraph(file);
        mazeGraph.print();
        out.println("Starting at 0\nGoal at 1");           
        DepthFirstSearch depthFirstSearch = new DepthFirstSearch(mazeGraph, startNode, goalNode);
        depthFirstSearch.printPath( goalNode);
        }

}

请向我解释为什么会发生这种情况并给我建议/建议如何改进这一点。检查我的代码质量是否正常,否则可以不检查。无论如何,先谢谢。

1 个答案:

答案 0 :(得分:2)

您实际上很幸运,您的算法找到了一个路径,因为它有一个主要缺陷:如果您离开递归调用,则不会取消设置visited。因此,您必须将此添加到performRecursiveDFS

private void performRecursiveDFS(MazeGraph mazeGraph, int node, int goal) {
    visited[node] = true; //set visited
    for (int arc : mazeGraph.getAdjacencyList(node)) {
        if (!visited[arc]) {
            pathTo[arc] = node;
            performRecursiveDFS(mazeGraph, arc, goal);

        }
    }
    visited[node] = false; //unset visited
}

这是必要的,因为你&#34; 回溯&#34;你正在寻找另一条道路,为此,你还没有去过node

此外,在递归调用中,您可以检查是否到达目标,如果是这种情况,请打印路径:

private void performRecursiveDFS(MazeGraph mazeGraph, int node, int goal) {
    visited[node] = true; //set visited
    if(node == goal) { //found the goal? Good, print it and backtrack.
        printPath(goal);
    } else {
        for (int arc : mazeGraph.getAdjacencyList(node)) {
            if (!visited[arc]) {
                pathTo[arc] = node;
                performRecursiveDFS(mazeGraph, arc, goal);
            }
        }
    }
    visited[node] = false; //unset visited
}

除了打印路径之外,您当然可以做其他事情,例如计数,将路径存储在列表中等等。

编辑:使用您提供的迷宫文件对其进行测试,我得到:

$ java DepthFirstSearch
Enter maze file: maze
Enter start node: 0
Enter goal node: 1
12 Nodes, 12 Arcs 

0 connected to 3 
1 connected to 4 
2 connected to 3 
3 connected to 11 2 0 
4 connected to 1 5 
5 connected to 4 7 
6 connected to 7 11 
7 connected to 5 6 8 11 
8 connected to 7 9 
9 connected to 8 10 
10 connected to 9 
11 connected to 3 6 7 
Starting at 0
Goal at 1
Path to Goal: 
0 - 3 - 11 - 6 - 7 - 5 - 4 - 1
Path to Goal: 
0 - 3 - 11 - 7 - 5 - 4 - 1