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

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

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

🌺The Begin🌺点点关注,收藏不迷路🌺

一、寻路算法概述

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

DFS寻路示例

0123456

从顶点0到顶点6的DFS路径可能是:0 → 1 → 4 → 6

二、算法核心思想

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

数据结构设计

Path-Graph G-int s-boolean[] visited-int[] from+dfs(int v)+hasPath(int w)+path(int w)+showPath(int w)

三、算法实现详解

1. 核心数据结构

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

2. 构造函数初始化

publicPath(Graph graph,int s){G= graph;assert s >=0&& s <G.V(); visited =newboolean[G.V()]; from =newint[G.V()];for(int i =0; i <G.V(); i++){ visited[i]=false; from[i]=-1;}this.s = s;dfs(s);}

3. DFS实现

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

4. 路径查询方法

booleanhasPath(int w){assert w >=0&& w <G.V();return visited[w];}Vector<Integer>path(int w){asserthasPath(w);Stack<Integer> s =newStack<>();int p = w;while(p !=-1){ s.push(p); p = from[p];}Vector<Integer> res =newVector<>();while(!s.empty()) res.add(s.pop());return res;}

四、完整代码实现

importjava.util.Stack;importjava.util.Vector;/** * 基于DFS的寻路算法 */publicclassPath{privateGraphG;// 图的引用privateint s;// 起始点privateboolean[] visited;// 记录访问过的节点privateint[] from;// 记录路径,from[i]表示i的前驱节点// 构造函数,寻路算法publicPath(Graph graph,int s){G= graph;assert s >=0&& s <G.V(); visited =newboolean[G.V()]; from =newint[G.V()];for(int i =0; i <G.V(); i++){ visited[i]=false; from[i]=-1;}this.s = s;// 开始DFS寻路dfs(s);}// 深度优先遍历privatevoiddfs(int v){ visited[v]=true;for(int i :G.adj(v)){if(!visited[i]){ from[i]= v;dfs(i);}}}// 判断是否有路径booleanhasPath(int w){assert w >=0&& w <G.V();return visited[w];}// 获取路径Vector<Integer>path(int w){asserthasPath(w);Stack<Integer> stack =newStack<>();int p = w;while(p !=-1){ stack.push(p); p = from[p];}Vector<Integer> res =newVector<>();while(!stack.empty()) res.add(stack.pop());return res;}// 打印路径voidshowPath(int w){asserthasPath(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();}}

五、算法测试与应用

测试代码

publicclassPathTest{publicstaticvoidmain(String[] args){// 创建一个图Graph g =newSparseGraph(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 =newPath(g,0);System.out.println("Path from 0 to 6:"); path.showPath(6);// 输出:0 -> 1 -> 4 -> 6System.out.println("Path from 0 to 5:"); path.showPath(5);// 输出:0 -> 2 -> 5System.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寻路对比

起点DFS vs BFSDFSBFS使用栈/递归不一定是最短路径使用队列保证最短路径

选择建议

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

八、实际应用场景

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

九、总结

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

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

DFS寻路算法是图算法的基础,虽然不能保证找到最短路径,但实现简单且在某些场景下效率很高。理解这一算法有助于学习更复杂的图算法如Dijkstra、A*等。

在这里插入图片描述

🌺The End🌺点点关注,收藏不迷路🌺

Read more

C++效率掌握之STL库:unordered_map && unordered_set底层剖析

C++效率掌握之STL库:unordered_map && unordered_set底层剖析

文章目录 * 1.unordered_map、unordered_set的基本结构 * 2.普通迭代器 * 3.const迭代器 * 4.insert返回值 operator[] * 希望读者们多多三连支持 * 小编会继续更新 * 你们的鼓励就是我前进的动力! 看了前面的底层封装后,其实封装的过程及方法都大差不差,unordered_map && unordered_set 也是如此,所以本篇就简单提及一些细节,具体最详细的一些部分可以去看前面的文章 传送门:C++效率掌握之STL库:list底层剖析及迭代器万字详解 传送门:C++效率掌握之STL库:map && set底层剖析及迭代器万字详解 1.unordered_map、unordered_set的基本结构 🚩unordered_set: template<classK,classV>

By Ne0inhk
C++《set与map》

C++《set与map》

在之前我们已经学习了解了C++STL当中的string和vector等容器,现在我们已经懂得了这些容器提供的接口该如何使用,并且了解了这些容器的底层结构。接下来我们在本篇当中将继续学习STL内的容器set与map,在此这两个容器与我们之前学习的容器提供的成员函数以及底层结构有细微的差异。接下来就开始本篇的学习吧!!! 1.顺序式容器与关联式容器  在了解set与map之前我们要先来了解什么是顺序式容器、什么是关联式容器。 前面我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间⼀般没有紧密的关联关系,比如交换⼀下,他依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位置来顺序保存和访问的。 关联式容器也是用来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是非线性结构,两个位置有紧密的关联关系,交换⼀下,他的存储结构就被破坏了。顺序容器中的元素是按关键字来保存和访问的。关联式容器有map/set系列和unor

By Ne0inhk
C++ 函数重载:规则、实现与实战案例

C++ 函数重载:规则、实现与实战案例

C++ 函数重载:规则、实现与实战案例 💡 学习目标:掌握函数重载的核心规则,能够熟练实现重载函数,并解决实际开发中重载相关的常见问题。 💡 学习重点:函数重载的匹配原则、与默认参数的冲突处理、实战场景中的重载应用。 一、函数重载的定义与核心价值 ✅ 结论:函数重载是 C++ 多态性的基础体现,允许同一作用域内定义多个同名函数,通过参数列表的差异区分调用。 函数重载的核心价值在于: 1. 简化函数命名,避免为功能相似的函数创建不同名称,提升代码可读性 2. 适配不同类型或数量的参数输入,让函数调用更灵活 ⚠️ 注意事项:函数返回值不能作为区分重载函数的依据。 例如以下代码是非法的: #include<iostream>usingnamespace std;// 非法重载:仅返回值不同intadd(int a,int b){return a + b;}doubleadd(int a,int

By Ne0inhk
C++ STL map 系列全方位解析:从基础使用到实战进阶

C++ STL map 系列全方位解析:从基础使用到实战进阶

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. map 核心概念:键值对与红黑树底层 * 1.1 什么是 map? * 1.2 关键类型定义 * 二. map 基础操作:构造、遍历与增删查改 * 2.1 构造与初始化 * 2.2 迭代器遍历 * 2.3 插入操作(insert) * 2.4 查找与删除(find/erase) * 2.5 核心特性:operator [] 的多功能性 * 三.

By Ne0inhk