You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在多维矩阵执行BFS遇循环引用无限循环,如何回溯获取路径?

BFS回溯无限循环的修复方案

你的代码里导致回溯无限循环的核心问题是parent数组的赋值逻辑完全搞反了,加上几个关键逻辑错误,下面逐个修正:

1. 核心错误:parent数组存储方向颠倒

你当前写的parent[current.getX()][current.getY()] = neighbor;,是把当前节点的父节点设成了邻居,完全搞反了逻辑——正确的应该是邻居节点的父节点是当前节点,也就是parent[neighbor.getX()][neighbor.getY()] = current;。

2. 目标节点的错误赋值

当current.equals(button)时,你错误地给parent[current.getX()][current.getY()] = previous;,这会覆盖掉当前节点的真实父节点(previous是上一次循环的current,并非当前节点的父节点),直接删掉这行即可。

3. visited集合的效率问题

用Queue<Cell>做visited集合,contains()方法是O(n)时间复杂度,效率极低且易出错,换成boolean[][] visited二维数组,直接通过坐标判断是否访问过,效率更高。

4. 移除冗余的previous变量

代码里的previous变量逻辑混乱,对路径回溯没有帮助,直接删除即可。

修复后的完整BFS代码

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class BFS {
    public List<Cell> breadthFirstSearch(Cell bot, Cell button, Fire fire, Ship ship) {
        int size = ship.getSize();
        // 二维数组记录访问状态,效率更高
        boolean[][] visited = new boolean[size][size];
        // parent数组:parent[x][y] 表示(x,y)节点的父节点,用于回溯路径
        Cell[][] parent = new Cell[size][size];
        Queue<Cell> queue = new LinkedList<>();

        // 初始化起点
        queue.add(bot);
        visited[bot.getX()][bot.getY()] = true;
        parent[bot.getX()][bot.getY()] = null;

        while (!queue.isEmpty()) {
            Cell current = queue.poll();
            System.out.println("当前遍历节点: " + current.toString());

            // 找到目标节点,开始回溯路径
            if (current.equals(button)) {
                List<Cell> path = new ArrayList<>();
                Cell node = current;
                while (node != null) {
                    path.add(node);
                    node = parent[node.getX()][node.getY()];
                    System.out.print("回溯节点: " + (node != null ? node.toString() : "null"));
                }
                // 反转得到从起点到终点的路径
                java.util.Collections.reverse(path);
                return path;
            }

            // 遍历当前节点的所有邻居
            for (Cell neighbor : getBotNeighbors(current)) {
                int nx = neighbor.getX();
                int ny = neighbor.getY();
                // 检查邻居是否合法:未燃烧、可通行、未被访问
                if (!ship.isBurning(nx, ny) && neighbor.isOpenCell(ship) && !visited[nx][ny]) {
                    visited[nx][ny] = true;
                    queue.add(neighbor);
                    // 关键:设置邻居的父节点为当前节点
                    parent[nx][ny] = current;
                }
            }
            System.out.println();
        }
        // 无路径返回空列表
        return new ArrayList<>();
    }

    // 实现邻居获取逻辑(需添加边界检查)
    private List<Cell> getBotNeighbors(Cell current) {
        List<Cell> neighbors = new ArrayList<>();
        int x = current.getX();
        int y = current.getY();
        // 上下左右四个方向,需根据网格边界过滤无效坐标
        neighbors.add(new Cell(x - 1, y));
        neighbors.add(new Cell(x + 1, y));
        neighbors.add(new Cell(x, y - 1));
        neighbors.add(new Cell(x, y + 1));
        return neighbors;
    }
}

// 补充Cell类(必须重写equals和hashCode)
class Cell {
    private int x;
    private int y;

    public Cell(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    // 重写equals确保坐标匹配时返回true
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Cell cell = (Cell) obj;
        return x == cell.x && y == cell.y;
    }

    @Override
    public int hashCode() {
        return java.util.Objects.hash(x, y);
    }

    @Override
    public String toString() {
        return "Cell{" + "x=" + x + ", y=" + y + '}';
    }
}

// 占位Ship和Fire类(根据实际实现调整)
class Ship {
    public int getSize() {
        return 5; // 对应示例5x5网格
    }

    public boolean isBurning(int x, int y) {
        return false; // 示例默认无燃烧区域
    }
}

class Fire {}

额外注意事项

  • 必须确保Cell类重写equals和hashCode方法,否则current.equals(button)会比较对象内存地址,永远返回false。
  • getBotNeighbors方法要添加边界检查,避免生成超出网格范围的无效坐标。

内容的提问来源于stack exchange,提问作者saanyay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 14:37:02