0

0

BFS路径搜索失败的常见陷阱:坐标哈希键冲突问题

花韻仙語

花韻仙語

发布时间:2025-12-31 13:37:13

|

731人浏览过

|

来源于php中文网

原创

BFS路径搜索失败的常见陷阱:坐标哈希键冲突问题

本文解析bfs在二维迷宫中无法找到目标值9的根本原因,重点指出使用无分隔符的字符串拼接(如"110")作为哈希键会导致不同坐标(如(1,10)与(11,0))哈希冲突,进而跳过合法节点;同时提供健壮、简洁的修复方案。

在实现基于广度优先搜索(BFS)的二维迷宫路径查找时,一个看似微小却极具破坏性的错误常导致算法“看似运行正常”却始终无法抵达目标(如值为 9 的终点)。问题核心并非逻辑结构或边界判断,而在于节点去重机制的设计缺陷

? 根本问题:坐标字符串键的哈希冲突

原代码中使用以下方式生成访问标记键:

String ps = Integer.toString(p.x) + Integer.toString(p.y);

该方式缺少分隔符,造成严重歧义。例如:

Endel.io
Endel.io

Endel是一款可以创造个性化舒缓声音的应用程序,可帮助您集中注意力、放松身心和入睡。

下载
  • 坐标 (1, 10) → "110"
  • 坐标 (11, 0) → "110"
    二者生成完全相同的字符串键,被 HashMap 视为同一节点。一旦 (1, 10) 被标记为已访问,(11, 0) 将永远被跳过——即使它通向目标,BFS 也会彻底遗漏该分支。
✅ 正确做法:强制引入唯一分隔符(如 ":", "," 或 "_") ❌ 错误示例:"110"、"12345"(无法区分 (12,345) 与 (123,45))

✅ 推荐修复方案(简洁 & 高效)

  1. 改用 Set 或自定义坐标类作为键(推荐)
    更语义化、零冲突、无需字符串操作:

    public static Set visited = new HashSet<>();
    // ...
    Point curr = new Point(p.x, p.y);
    visited.add(curr); // 自动去重(需确保 Point 正确重写 equals/hashCode)
  2. 若坚持字符串键,请严格使用带分隔符格式

    String key = p.x + "," + p.y; // 如 "1,10" ≠ "11,0"
    if (!visited.contains(key)) {
        visited.add(key);
        q.add(new Box(p.x, p.y, p));
    }
  3. 优化数据结构:用 Set 替代 Map
    原 HashMap 本质是模拟集合,既冗余又易错。直接使用 HashSet 或 HashSet 更清晰、内存更优。

? 完整修正要点(关键片段)

public static Queue q = new LinkedList<>();
public static Set visited = new HashSet<>(); // ← 改为 Set

public static void searchPath(int[][] maze, int x, int y, ArrayList path) {
    q.add(new Box(x, y, null));
    visited.add(x + "," + y); // ← 入队即标记

    while (!q.isEmpty()) {
        Box p = q.poll();

        if (maze[p.y][p.x] == 9) {
            System.out.println("target found!");
            getPath(p, maze, path);
            return;
        }

        // 四方向扩展(以右为例,其余同理)
        int[] dx = {1, -1, 0, 0}, dy = {0, 0, 1, -1};
        for (int i = 0; i < 4; i++) {
            int nx = p.x + dx[i], ny = p.y + dy[i];
            String nextKey = nx + "," + ny;

            if (isFree(maze, nx, ny) && !visited.contains(nextKey)) {
                visited.add(nextKey);
                q.add(new Box(nx, ny, p));
            }
        }
    }
    System.out.println("exited without finding target");
}

⚠️ 注意事项与最佳实践

  • 始终验证 isFree() 的索引顺序:代码中 maze[y][x] 是标准行列约定(y 行、x 列),确保输入迷宫维度匹配(maze.length 为行数,maze[0].length 为列数)。
  • 避免静态变量污染:当前 q 和 visited 为 static,多线程或多次调用会互相干扰。生产环境应封装为实例方法或局部变量。
  • 路径重建健壮性:getPath() 中未检查 path 是否为 null,建议添加判空逻辑。
  • 性能提示:对大规模迷宫,String 键存在对象创建开销,Point 类(配合 record 或正确 hashCode)更高效。

通过修正哈希键设计,BFS 将真正实现“无遗漏、无重复”的层级遍历,确保目标可达时必被发现。记住:BFS 的正确性,始于每一个坐标的唯一身份标识。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

312

2023.08.02

java中boolean的用法
java中boolean的用法

在Java中,boolean是一种基本数据类型,它只有两个可能的值:true和false。boolean类型经常用于条件测试,比如进行比较或者检查某个条件是否满足。想了解更多java中boolean的相关内容,可以阅读本专题下面的文章。

346

2023.11.13

java boolean类型
java boolean类型

本专题整合了java中boolean类型相关教程,阅读专题下面的文章了解更多详细内容。

19

2025.11.30

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

229

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

433

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

248

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

205

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1435

2023.10.24

vlookup函数使用大全
vlookup函数使用大全

本专题整合了vlookup函数相关 教程,阅读专题下面的文章了解更多详细内容。

28

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号