跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

图的寻路算法详解:深度优先搜索 (DFS) 的 Java 实现

深度优先搜索 (DFS) 是图论中寻找路径的基础算法之一。通过 Java 语言实现了基于 DFS 的寻路类,利用 from 数组记录前驱节点以回溯路径。核心流程包括初始化访问标记、递归遍历邻接点以及逆向构建路径。相比广度优先搜索 (BFS),DFS 不保证最短路径但实现简单且内存占用较低,适用于迷宫求解、网络路由及依赖分析等场景。文章还对比了两种算法的差异,并分析了时间与空间复杂度。

城市逃兵发布于 2026/3/27更新于 2026/7/2146 浏览
图的寻路算法详解:深度优先搜索 (DFS) 的 Java 实现

图的寻路算法详解:基于深度优先搜索 (DFS) 的实现

一、寻路算法概述

图的寻路算法是图论中的基础应用之一,主要解决从一个顶点到另一个顶点是否存在路径以及如何找到该路径的问题。深度优先搜索 (DFS) 是实现这一目标的有效方法,它沿着图的深度方向尽可能远地搜索,直到无法继续为止。

DFS 寻路示例

假设我们有一个无向图,从顶点 0 出发寻找至顶点 6 的路径。DFS 可能会遍历出如下序列:

0 → 1 → 4 → 6

二、算法核心思想

实现 DFS 寻路主要依赖三个关键点:

  1. 记录路径:使用 from 数组记录每个顶点的前驱顶点,以便后续回溯。
  2. 深度优先遍历:从起点开始递归访问所有未访问的邻接顶点。
  3. 路径回溯:通过 from 数组逆向追踪,还原出完整的访问路径。
数据结构设计

我们需要维护以下核心状态:

  • visited 数组:标记顶点是否已被访问。
  • from 数组:记录路径中每个顶点的前驱节点索引。
  • s:起始顶点的索引。

三、算法实现详解

1. 核心数据结构

在 Java 实现中,我们通常定义一个内部类或独立类来封装这些逻辑。关键成员变量包括图的引用、起始点、访问标记数组和前驱数组。

2. 初始化逻辑

构造函数负责初始化图引用和辅助数组。这里需要特别注意边界检查,确保起始点有效。同时,为了支持多次查询,我们在构造时直接执行一次 DFS 遍历,预先计算好从起点出发的所有可达路径信息。

public Path(Graph graph, int s) {
    G = graph;
    assert s >= 0 && s < G.V();
    visited = new boolean[G.V()];
    from = new int[G.V()];
    for (int i = 0; i < G.V(); i++) {
        visited[i] = false;
        from[i] = -1;
    }
    this.s = s;
    dfs(s);
}
3. DFS 实现

这是算法的核心递归部分。当我们访问一个顶点 v 时,将其标记为已访问,然后遍历其所有邻接点。如果邻接点未被访问,则更新其前驱为当前顶点 v,并递归调用自身。

private void  {
    visited[v] = ;
     ( i : G.adj(v)) {
         (!visited[i]) {
            from[i] = v; 
            dfs(i);
        }
    }
}
dfs
(int v)
true
for
int
if
// 记录前驱顶点
4. 路径查询方法

查询路径分为两步:首先判断是否有路径(即终点是否被访问过),如果有,则利用栈结构从终点逆向回溯至起点,再翻转得到正序路径。

boolean hasPath(int w) {
    assert w >= 0 && w < G.V();
    return visited[w];
}

Vector<Integer> path(int w) {
    assert hasPath(w);
    Stack<Integer> stack = new Stack<>();
    int p = w;
    while (p != -1) {
        stack.push(p);
        p = from[p];
    }
    Vector<Integer> res = new Vector<>();
    while (!stack.empty()) res.add(stack.pop());
    return res;
}

四、完整代码实现

以下是整合后的 Path 类,包含必要的导入和注释,可直接用于测试。

import java.util.Stack;
import java.util.Vector;

/**
 * 基于 DFS 的寻路算法
 */
public class Path {
    private Graph G;          // 图的引用
    private int s;            // 起始点
    private boolean[] visited;// 记录访问过的节点
    private int[] from;       // 记录路径,from[i]表示i的前驱节点

    // 构造函数,寻路算法
    public Path(Graph graph, int s) {
        G = graph;
        assert s >= 0 && s < G.V();
        visited = new boolean[G.V()];
        from = new int[G.V()];
        for (int i = 0; i < G.V(); i++) {
            visited[i] = false;
            from[i] = -1;
        }
        this.s = s;
        // 开始 DFS 寻路
        dfs(s);
    }

    // 深度优先遍历
    private void dfs(int v) {
        visited[v] = true;
        for (int i : G.adj(v)) {
            if (!visited[i]) {
                from[i] = v;
                dfs(i);
            }
        }
    }

    // 判断是否有路径
    boolean hasPath(int w) {
        assert w >= 0 && w < G.V();
        return visited[w];
    }

    // 获取路径
    Vector<Integer> path(int w) {
        assert hasPath(w);
        Stack<Integer> stack = new Stack<>();
        int p = w;
        while (p != -1) {
            stack.push(p);
            p = from[p];
        }
        Vector<Integer> res = new Vector<>();
        while (!stack.empty()) res.add(stack.pop());
        return res;
    }

    // 打印路径
    void showPath(int w) {
        assert hasPath(w);
        Vector<Integer> vec = path(w);
        for (int i = 0; i < vec.size(); i++) {
            System.out.print(vec.elementAt(i));
            if (i != vec.size() - 1)
                System.out.print(" -> ");
        }
        System.out.println();
    }
}

五、算法测试与应用

为了验证算法的正确性,我们可以构建一个简单的稀疏图进行测试。

测试代码
public class PathTest {
    public static void main(String[] args) {
        // 创建一个图
        Graph g = new SparseGraph(7, false);
        g.addEdge(0, 1);
        g.addEdge(0, 2);
        g.addEdge(1, 3);
        g.addEdge(1, 4);
        g.addEdge(2, 5);
        g.addEdge(4, 6);

        // 寻路算法测试
        Path path = new Path(g, 0);
        System.out.println("Path from 0 to 6:");
        path.showPath(6); // 输出:0 -> 1 -> 4 -> 6

        System.out.println("Path from 0 to 5:");
        path.showPath(5); // 输出:0 -> 2 -> 5

        System.out.println("Has path to 3: " + path.hasPath(3));
        System.out.println("Has path to 6: " + path.hasPath(6));
    }
}
输出结果
Path from 0 to 6: 0 -> 1 -> 4 -> 6 
Path from 0 to 5: 0 -> 2 -> 5 
Has path to 3: true 
Has path to 6: true 

六、算法分析与优化

时间复杂度分析
操作时间复杂度
初始化O(V)
DFS 遍历O(V + E)
路径查询O(L) L 为路径长度
空间复杂度

主要消耗在于 visited 和 from 数组以及递归栈,总体为 O(V)。

优化方向
  1. 广度优先搜索 (BFS):如果需要最短路径,BFS 是更好的选择。
  2. 双向搜索:同时从起点和终点开始搜索,减少搜索空间。
  3. 启发式搜索:如 A*算法,适用于有权图或具有距离信息的场景。

七、DFS 寻路与 BFS 寻路对比

特性DFSBFS
数据结构栈 / 递归队列
路径性质任意路径保证最短路径
内存消耗较低较高

选择建议:

  • 只需要找到任意一条可行路径,且对路径长度不敏感时,使用 DFS。
  • 必须找到最短路径(边数最少)时,使用 BFS。
  • 图规模非常大且内存受限,DFS 通常更友好。

八、实际应用场景

DFS 寻路在实际开发中非常常见,例如:

  1. 迷宫求解
  2. 网络路由协议
  3. 社交网络中查找关系链
  4. 游戏中的 AI 路径规划
  5. 依赖关系解析(如 Maven/Gradle 依赖树)

九、总结

本文详细介绍了基于 DFS 的图寻路算法,涵盖了核心思想、数据结构设计、Java 完整实现以及复杂度分析。虽然 DFS 不能保证找到最短路径,但其实现简单、逻辑清晰,且在特定场景下效率很高。理解这一算法是掌握更复杂图算法(如 Dijkstra、A*)的重要基石。

目录

  1. 图的寻路算法详解:基于深度优先搜索 (DFS) 的实现
  2. 一、寻路算法概述
  3. DFS 寻路示例
  4. 二、算法核心思想
  5. 数据结构设计
  6. 三、算法实现详解
  7. 1. 核心数据结构
  8. 2. 初始化逻辑
  9. 3. DFS 实现
  10. 4. 路径查询方法
  11. 四、完整代码实现
  12. 五、算法测试与应用
  13. 测试代码
  14. 输出结果
  15. 六、算法分析与优化
  16. 时间复杂度分析
  17. 空间复杂度
  18. 优化方向
  19. 七、DFS 寻路与 BFS 寻路对比
  20. 八、实际应用场景
  21. 九、总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C++ 多容器非空检查的逻辑陷阱与最佳实践
  • 相干伊辛机在医疗与医疗 AI 领域的应用前景
  • OpenClaw 与 Telegram 机器人集成指南
  • OpenClaw 集成 Telegram 机器人开发指南
  • C/C++ 中 const 关键字的用法与差异详解
  • Java IO API 获取文件元素的方法
  • Jetpack Compose 完全开发手册:从入门到精通
  • VRM4U插件完整指南:在Unreal Engine 5中高效处理VRM模型
  • Java 数据结构:链表原理与 LinkedList 核心应用
  • 从前端到 DevOps:各类开发者 AI 工作流工具
  • OpenClaw 飞书机器人权限配置与安全指南
  • Linux 库的制作与原理
  • Web 创建与设计指南
  • Python 真的有必要学吗?基于工作场景的实用性分析
  • 多智能体协作驱动的多模态医疗大模型系统:RAG-KAG 双路径知识增强与架构设计
  • 无人机低空智能巡飞巡检平台:全域感知与智能决策
  • 医疗 AI 驱动下医院数据仓库的智能化升级:异构采集与精准评估
  • Claude Code的完美平替:OpenCode + GitHub Copilot
  • FPGA 入门实战:基于 Quartus 点亮 LED 灯
  • Freqtrade 新手教程:macOS + Docker 环境配置与回测

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online