简体   繁体   English

二维网格中的 BFS 搜索 Java 最短路径

[英]BFS search in 2D grid Java shortest path

I've managed to come up with a working BFS algorithm that returns the entire traversal path, however I'm unsure of how to get the shortest path.我设法提出了一个返回整个遍历路径的有效 BFS 算法,但是我不确定如何获得最短路径。

This is my code:这是我的代码:

public ArrayList<Node> get_neighbours(Node node, Grid grid) {

        ArrayList<Node> neighbours = new ArrayList<>();

        int R = grid.getRl();
        int C = grid.getCl();

        int[] dr = new int[]{-1, +1, 0, 0};
        int[] dc = new int[]{0, 0, +1, -1};

        for (int i=0; i<4; i++) {
            int rr = node.getR() + dr[i];
            int cc = node.getC() + dc[i];

            if (rr < 0 || cc < 0) continue;
            if (rr >= R || cc >= C) continue;

            if (grid.getNodes()[rr][cc].getVal() == "V") continue;
            if (grid.getNodes()[rr][cc].getVal() == "X") continue;

            Node neighbour = grid.getNodes()[rr][cc];
            neighbours.add(neighbour);
        }

        return neighbours;

    }

    public Queue<Node> find_path_bfs(Node start, Node end, Grid grid) {

        Queue<Node> queue = new LinkedList<>();
        Queue<Node> path = new LinkedList<>();

        queue.add(start);
        grid.mark_visited(start.getR(), start.getC());

        while (!queue.isEmpty()) {
            Node node = queue.remove();
            path.add(node);

            if (node == end) break;

            ArrayList<Node> adj_nodes = get_neighbours(node, grid);
            for (Node n : adj_nodes) {
                if (!(n.getVal() == "V")) {
                    queue.add(n);
                    n.setVal("V");
                }
            }
        }
        return path;
    }

I took a look at this post , that suggests saving the path to the current node as well, but I'm not sure how to implement this in Java as I would have to have a queue that stores both a Node and a List of Nodes together as one item.我看了一下这篇文章,建议也保存当前节点的路径,但我不确定如何在 Java 中实现这一点,因为我必须有一个存储节点和节点列表的队列一起作为一个项目。 My Java is a little rusty, so I'm not sure if this is possible or if there is a better way.我的 Java 有点生锈,所以我不确定这是否可行或者是否有更好的方法。

Your issue is that right now you're using the Queue<Node> path variable as a visited list, rather than a path list.您的问题是,现在您使用Queue<Node> path变量作为访问列表,而不是路径列表。 Instead of building the path as you go, store references to each child node's parent and then traverse back through this.不要像 go 那样构建路径,而是存储对每个子节点的父节点的引用,然后遍历它。 Something like this:像这样的东西:

public ArrayList<Node> find_path_bfs(Node start, Node end, Grid grid) {

    Queue<Node> queue = new LinkedList<>();
    List<Node> path = new ArrayList<>();

    queue.add(start);
    grid.mark_visited(start.getR(), start.getC());

    Map<Node, Node> parentMap = new HashMap<>();

    Node node = start;
    parentMap.put(start, null); // start node has no parent, so we end path reconstruction here
    while (!queue.isEmpty()) {
        node = queue.remove();
        // path.add(node);

        if (node == end) break;

        ArrayList<Node> adj_nodes = get_neighbours(node, grid);
        for (Node n : adj_nodes) {
            if (!(n.getVal() == "V")) {
                queue.add(n);
                parentMap.put(n, node); // mark current node as parent to neighbor
                n.setVal("V");
            }
        }
    }

    Node curr = node;
    while (curr != null) {
        path.add(0, curr);
        curr = parentMap.get(curr);
    }

    return path;
}

I changed path to an ArrayList so that you can insert at the beginning (since you're reconstructing the path from the last node, rather than the first one).我将路径更改为 ArrayList 以便您可以在开头插入(因为您正在从最后一个节点而不是第一个节点重建路径)。 Alternatively, you could keep it as a Queue and reverse the order of the elements.或者,您可以将其保留为队列并颠倒元素的顺序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM