图的寻路算法详解:基于深度优先搜索(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

【算法】【优选算法】BFS 解决拓扑排序

【算法】【优选算法】BFS 解决拓扑排序

目录 * 一、拓扑排序 * 1.1 有向无环图(DAG图) * 1.2 AOV 网:顶点活动图 * 1.3 拓扑排序 * 1.4 实现拓扑排序 * 二、207. 课程表 * 三、210. 课程表 II * 四、LCR 114. ⽕星词典 一、拓扑排序 1.1 有向无环图(DAG图) 有向无环图:有向无环图:一个无回路的有向图,如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个有向无环图(DAG图)。 1.2 AOV 网:顶点活动图 在有向无环图的基础上,用顶点来表示一个活动,用边来表示活动执行的先后顺序。 1.

By Ne0inhk
【优选算法必刷100题】第027~28题(前缀和算法):寻找数组的中心下标、除自身以外数组的乘积

【优选算法必刷100题】第027~28题(前缀和算法):寻找数组的中心下标、除自身以外数组的乘积

🔥艾莉丝努力练剑:个人主页 ❄专栏传送门:《C语言》、《数据结构与算法》、C/C++干货分享&学习过程记录、Linux操作系统编程详解、笔试/面试常见算法:从基础到进阶 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬艾莉丝的简介: 🎬艾莉丝的算法专栏简介: 目录 027  寻找数组的中心下标  1.1  算法思路:前缀和 1.2  算法实现 1.2.1  C++实现 1.2.2  Java实现 1.3  博主手记 028  除自身以外数组的乘积 2.1  算法思路 2.2  算法实现

By Ne0inhk

LeetCode.2612最少翻转次数C++

【题目描述】 一个长度为n的数字arr,该数组中除了下标为p的位置为1,其他位置均为0。 一个banned数组,它的内容表示arr数组中的位置,也就是满足所有的arr[banned[i]]=0,其中banned[i]!=p。 返回一个大小为n的数组ans,其中ans[i]表示:数组arr经过多少次翻转可以让i位置出现1。 如果不能实现,则ans[i]=-1。 " 翻转大小为k的子数组,是指将该子数组逆序。" 【思路】 1,首先知道arr数组中p位置的值为1,即arr[p]=1,其余位置为0。目标是翻转大小为k的子数组,使得其他位置也出现1,求每个位置的翻转次数。 那么ans[p]=0,因为p位置不用翻转,本来就是1,所以翻转次数为0。 假设现在i位置的值为1。假设下标i经过一次翻转后的下标为j,这个下标j肯定不是一个特定的下标,它代表翻转后的所有可能的下标。那么我们可以将i和j看成用一条边连接,这条边的边权为1,表示从i位置翻转到j位置的翻转次数。可以理解为求最短路径的过程。

By Ne0inhk
【大数据存储与管理】分布式文件系统HDFS:07 HDFS编程实践

【大数据存储与管理】分布式文件系统HDFS:07 HDFS编程实践

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈大数据技术原理与应用 ⌋ ⌋ ⌋专栏系统介绍大数据的相关知识,分为大数据基础篇、大数据存储与管理篇、大数据处理与分析篇、大数据应用篇。内容包含大数据概述、大数据处理架构Hadoop、分布式文件系统HDFS、分布式数据库HBase、NoSQL数据库、云数据库、MapReduce、Hadoop再探讨、数据仓库Hive、Spark、流计算、Flink、图计算、数据可视化,以及大数据在互联网领域、生物医学领域的应用和大数据的其他应用。 【GitCode】专栏资源保存在我的GitCode仓库:https://gitcode.com/Morse_Chen/BigData_principle_application。 文章目录 * 一、HDFS常用命令 * 二、HDFS的Web页面 * 三、HDFS常用Java API及应用实例 * (一)常用Java API介绍 * (二)应用实例 * 总结

By Ne0inhk