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

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

图寻路算法用于寻找图中两点间的路径。深度优先搜索 (DFS) 通过递归遍历邻接顶点记录路径前驱,实现简单但未必最短。介绍基于 Java 的 DFS 寻路类 Path,包含数据结构设计、初始化、核心遍历及路径回溯方法。代码展示了如何构建图、执行 DFS 并输出路径结果。分析了时间复杂度 O(V+E) 和空间复杂度 O(V),并与广度优先搜索 (BFS) 对比,指出 DFS 适用于任意路径查找,而 BFS 保证最短路径。应用场景涵盖迷宫求解、网络路由及游戏 AI 规划等。

abccba发布于 2026/2/9更新于 2026/10/26108 浏览
图的寻路算法详解:基于深度优先搜索 (DFS) 的实现

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

一、寻路算法概述

图的寻路算法是图论中的基础算法之一,用于找到从一个顶点到另一个顶点的路径。深度优先搜索 (DFS) 是实现寻路算法的一种有效方法,它沿着图的深度方向尽可能远地搜索路径。

DFS 寻路示例

假设有一个图,从顶点 0 到顶点 6 的 DFS 路径可能是:0 → 1 → 4 → 6。

二、算法核心思想

  1. 记录路径:使用 from 数组记录每个顶点的前驱顶点。
  2. 深度优先遍历:从起点开始递归访问所有未访问的邻接顶点。
  3. 路径回溯:通过 from 数组逆向回溯找到完整路径。

数据结构设计

  • G:图的引用
  • s:起始顶点
  • visited:布尔数组,记录顶点是否被访问过
  • from:整型数组,记录路径中每个顶点的前驱顶点
  • 方法:dfs(int v), hasPath(int w), path(int w), showPath(int w)

三、算法实现详解

1. 核心数据结构

  • visited 数组:记录顶点是否被访问过
  • from 数组:记录路径中每个顶点的前驱顶点
  • s:起始顶点

2. 构造函数初始化

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 实现

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

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;
}

四、完整代码实现

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 为路径长度

空间复杂度

  • O(V) 用于存储 visited 和 from 数组

优化方向

  1. 广度优先搜索 (BFS):可以找到最短路径
  2. 双向搜索:同时从起点和终点开始搜索
  3. 启发式搜索:如 A* 算法,适用于有权图

七、DFS 寻路与 BFS 寻路对比

特性DFSBFS
数据结构栈/递归队列
路径性质不一定是最短路径保证最短路径

选择建议:

  • 需要找到任意路径时使用 DFS
  • 需要找到最短路径时使用 BFS
  • 图非常大时 DFS 内存消耗更少

八、实际应用场景

  1. 迷宫求解
  2. 网络路由
  3. 社交网络中查找关系链
  4. 游戏中的 AI 路径规划
  5. 依赖关系解析

九、总结

本文详细介绍了基于 DFS 的图寻路算法,重点讲解了:

  1. 算法核心思想和数据结构设计
  2. 完整的 Java 实现代码
  3. 算法的时间复杂度和空间复杂度分析
  4. 与 BFS 寻路的对比
  5. 实际应用场景

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. 九、总结

更多推荐文章

查看全部
  • 二叉排序树与堆的区别
  • 从前端到 DevOps:各类开发者 AI 工作流工具
  • Open-Lovable 网页克隆工具本地部署与远程访问方案
  • 2026 年知网 AIGC 检测算法升级解读
  • Java 中 ML-KEM 密钥封装机制的 5 大核心实现步骤
  • 大模型 API 注册与调用实战:OpenAI、文心一言、通义千问
  • Spatial Joy 2025 全球 AR&AI 赛事:开发者资源与参赛指南
  • 开源医疗大模型排行榜:健康领域基准测试与评估
  • C/C++ 错误处理机制与常用函数
  • Vivado 入门实战:D 触发器设计与烧录流程
  • ZeroClaw 本地 AI 管理面板:Gateway + LM Studio + Reflex
  • Kimi-VL-A3B-Thinking 部署与 vLLM 性能调优实战
  • 基于 LLaMA-Factory 的大模型 LoRA 微调实战指南
  • FPGA FIFO IP 核配置与原理详解
  • Java 核心技术面试知识点总结
  • Web 聊天室消息加解密方案详解
  • Llama 开源家族梳理:从 Llama-1 到 Llama-3
  • 20 个提升 Python 开发效率的 PyCharm 常用插件推荐
  • 鸿蒙生态共建:智慧医疗领域的分布式革新与实践
  • Python 数据统计入门与实战指南

相关免费在线工具

  • 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