【算法基础实验】图论-深度优先搜索和深度优先路径

深度优先(DFS)

理论基础

深度优先搜索(DFS, Depth-First Search)是图和树的遍历算法中的一种,它从一个节点开始,沿着树的边走到尽可能深的分支,直到节点没有子节点为止,然后回溯继续搜索下一个分支。DFS 是一种使用递归或栈实现的算法,它深入到每一个分支直到无路可走再退回到上一个分岔点,这种方式有助于解决许多搜索和路径问题。

DFS 的基本步骤

  1. 标记和访问:从一个未访问的节点开始,标记它为已访问。
  2. 递归探索:对于当前节点的每一个未访问的相邻节点,继续执行深度优先搜索(递归调用DFS)。
  3. 回溯:当一个节点的所有相邻节点都被访问后,回溯到之前的节点继续探索未访问的节点。

DFS 的特点

  • 深度优先:它尝试尽可能深地搜索图的分支。
  • 使用栈:无论是显式使用栈还是通过递归调用的隐式栈,DFS 都利用栈先进后出的特性来管理节点和回溯。
  • 可能非最短路径:DFS 不保证找到的是最短路径,它可能在找到目标前遍历图中大部分节点。
  • 解空间树:在涉及路径和状态的问题中,DFS 常用于生成解空间树,并通过回溯剪枝。
  • 复杂性:在最坏的情况下,DFS 的时间复杂度是 O(V+E),其中 V 是顶点数,E 是边数。

DFS 的应用场景

  • 路径搜索:在迷宫或图中查找从起点到终点的路径。
  • 拓扑排序:在有向无环图中进行拓扑排序。
  • 连通分量:在无向图中查找所有连通分量。
  • 解决问题:如解决迷宫问题、路径问题和那些可以通过回溯方法解决的问题。

简单总结

深度优先搜索是一个递归的过程,它尝试深入到每一个分支直到不能再深入为止,然后通过回溯继续探索其他分支。它的核心在于尝试所有可能的路径直到找到解决方案或覆盖所有的节点。DFS 的记忆点在于它的递归性质和回溯机制,这使得它非常适合处理需要探索所有可能性的问题。

前提

JAVA实验环境

实现Bag抽象数据结构

实现Stack抽象数据结构

实现无向图的构建

数据结构

本算发中涉及到的基本数据结构

private boolean[] marked
private int[] edgeTo
private final int s
myLinkedStack //一种栈的实现,具体见以下链接
myGraph //一种无向图的实现

myGraph的数据结构图

请添加图片描述

实验数据和实验环境

本实验要求根据DFS算法实现从任意一点的深度优先路径的打印功能

实验数据是一个名为tinyCG.txt的文件,用来构建如下图所示的无向图

请添加图片描述

算法流程

请添加图片描述

根据以上深度优先搜索得到的结果,整理输出从起点到图中所有点的

下图为从0到5的深度优先路劲的计算过程,我们可以计算出从任意起点到其他所有点的深度优先路径

请添加图片描述

代码实现

import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;public class myDepthFirstPaths {private boolean[] marked;private int[] edgeTo;private final int s;public myDepthFirstPaths(myGraph G, int s){this.s = s;marked = new boolean[G.V()];edgeTo = new int[G.V()];dfs(G, s);}private void dfs(myGraph G, int v){marked[v] = true;for(int w:G.adj(v))if(!marked[w]){edgeTo[w]=v;dfs(G,w);}}public boolean hasPathTo(int v){return marked[v];}public Iterable<Integer> pathTo(int v){if(!hasPathTo(v)) return null;myLinkedStack<Integer> path = new myLinkedStack<Integer>();for(int x=v;x!=s;x=edgeTo[x]) path.push(x);path.push(s);return path;}public static void main(String[] args){myGraph G = new myGraph(new In(args[0]));int s = Integer.parseInt(args[1]);myDepthFirstPaths search = new myDepthFirstPaths(G,s);for(int v=0; v < G.V(); v++){StdOut.print(s+" to "+v+":");if(search.hasPathTo(v)){for(int x:search.pathTo(v))if(x==s) StdOut.print(x);else StdOut.print("-"+x);StdOut.println();}}}
}

代码详解

这段代码实现了一个用于无向图的深度优先搜索(DFS)路径查找类 myDepthFirstPaths。它可以找到从一个给定的起始顶点 s 到图中任意其他顶点的路径。以下是代码的详细解读和功能介绍:

类定义与变量


public class myDepthFirstPaths {private boolean[] marked;  // 用于标记每个顶点是否已被访问private int[] edgeTo;      // 从起点到一个顶点的已知路径上的最后一个顶点private final int s;       // 起始顶点
  • marked[] 数组用于跟踪每个顶点是否被访问过。
  • edgeTo[] 数组记录到达每个顶点的最后一步的前一个顶点。
  • s 是算法开始的起点。

构造函数


public myDepthFirstPaths(myGraph G, int s){this.s = s;marked = new boolean[G.V()];edgeTo = new int[G.V()];dfs(G, s);
}

构造函数初始化 markededgeTo 数组,并从顶点 s 开始对图 G 进行深度优先搜索。

深度优先搜索方法


private void dfs(myGraph G, int v){marked[v] = true;for(int w: G.adj(v))if(!marked[w]){edgeTo[w] = v;dfs(G, w);}
}

这是一个递归方法,它标记顶点 v 为已访问,然后对于每个与 v 相邻的未访问顶点 w,记录 w 是从 v 达到的,并递归地继续深度优先搜索。

路径检查与生成


public boolean hasPathTo(int v){return marked[v];
}public Iterable<Integer> pathTo(int v){if (!hasPathTo(v)) return null;myLinkedStack<Integer> path = new myLinkedStack<Integer>();for (int x = v; x != s; x = edgeTo[x])path.push(x);path.push(s);return path;
}
  • hasPathTo 方法检查是否存在从起点 s 到顶点 v 的路径。
  • pathTo 方法返回从起点 s 到顶点 v 的路径,使用一个自定义的栈 myLinkedStack 来逆序存储路径。

主方法


public static void main(String[] args){myGraph G = new myGraph(new In(args[0]));int s = Integer.parseInt(args[1]);myDepthFirstPaths search = new myDepthFirstPaths(G, s);for (int v = 0; v < G.V(); v++){StdOut.print(s + " to " + v + ":");if (search.hasPathTo(v)){for (int x : search.pathTo(v))if (x == s) StdOut.print(x);else StdOut.print("-" + x);}StdOut.println();}
}

主方法从文件中读取图,并从指定的起点 s 开始搜索。对于图中的每个顶点 v,如果存在从 sv 的路径,则打印该路径。

这个程序展示了如何使用深度优先搜索来找出图中从一个特定起点到所有其他顶点的路径。这些路径可以用于多种应用,比如网络路由、社交网络中的连接查找等。

实验

编译代码

javac myDepthFirstPaths.java

运行代码

代码运行要输入两个参数,首先是用于构造无向图的tinyCG.txt文件,第二个是起点的数值

最终的打印结果是从0分别到1,2,3,4,5的深度优先路径

java myDepthFirstPaths tinyCG.txt 0 
0 to 0:0
0 to 1:0-2-1
0 to 2:0-2
0 to 3:0-2-3
0 to 4:0-2-3-4
0 to 5:0-2-3-5

参考资料

算法(第4版)人民邮电出版社

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/316322.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索Jellyfin:支持Android的自由开源的媒体服务器平台

探索Jellyfin&#xff1a;支持Android的自由开源的媒体服务器平台 I. 简介 A. 什么是Jellyfin&#xff1f; Jellyfin是一个自由开源的媒体服务器平台&#xff0c;旨在让用户能够自主管理和流式传输他们的媒体内容。与许多闭源的商业媒体服务器解决方案不同&#xff0c;Jelly…

C++入门第一节-前言

写在前面 hello&#xff0c;小伙伴们大家好&#xff0c;我们都知道&#xff0c;C是在C语言的基础上进行的延伸和补充&#xff0c;所以我们学习C语言&#xff0c;数据结构等等&#xff0c;已经为C打下了基础&#xff08;C兼容C语言&#xff09;&#xff0c;从今天开始&#xff0…

深度学习基础之《TensorFlow框架(16)—神经网络案例》

一、mnist手写数字识别 1、数据集介绍 mnist数据集是一个经典的数据集&#xff0c;其中包括70000个样本&#xff0c;包括60000个训练样本和10000个测试样本 2、下载地址&#xff1a;http://yann.lecun.com/exdb/mnist/ 3、文件说明 train-images-idx3-ubyte.gz: training s…

vue2 实现echarts图表进入可视区域后再加载动画,以及 使用了resize之后,动画失效问题解决

Intersection Observer API 是一个现代的浏览器 API&#xff0c;用于监测一个或多个目标元素与其祖先元素或视窗&#xff08;viewport&#xff09;之间的交叉状态&#xff08;intersection&#xff09;的变化。它可以有效地监听元素是否进入或离开可视区域&#xff0c;从而实现…

Linux基础-socket详解、TCP/UDP

文章目录 一、Socket 介绍二、Socket 通信模型三、Socket 常用函数1 创建套接字2 绑定套接字3、监听连接4、接受连接5、接收和发送数据接收数据发送数据 6、关闭套接字 四、Socket编程试验1、源码server.cclient.c 2、编译&#xff1a;3、执行结果 五、补充TCP和UDP协议的Socke…

万兴PDF专家 PDFelement Pro v10.3.8 破姐版!

&#x1f9d1;‍&#x1f4bb;万兴PDF专家 PDFelement Pro v10.3.8 破姐版 (https://docs.qq.com/sheet/DRVVxTHJ3RXJFVHVr)

go项目实战——动手写分布式缓存GeeCache

文章目录 FIFO/LFU/LRU 算法简介FIFO(First In First Out)LFU(Least Frequently Used)LRU(Least Recently Used) LRU实现实现原理LRU代码说明LRU完整代码 单机并发缓存Http服务器一致性哈希分布式节点防止缓存击穿使用 Protobuf 通信项目Get流程参考资料 FIFO/LFU/LRU 算法简介…

您可知道如何通过`HTTP2`实现TCP的内网穿透???

可能有人很疑惑应用层 转发传输层&#xff1f;&#xff0c;为什么会有这样的需求啊&#xff1f;&#xff1f;&#xff1f;哈哈技术无所不用其极&#xff0c;由于一些场景下&#xff0c;对于一个服务器存在某一个内部网站中&#xff0c;但是对于这个服务器它没有访问外网的权限&…

Python数据分析大作业(ARIMA 自回归积分滑动平均模型) 4000+字 图文分析文档 销售价格库存分析+完整python代码

资源地址&#xff1a;Python数据分析大作业 4000字 图文分析文档 销售分析 完整python代码 完整代码分析 ​ 同时销售量后1000的sku品类占比中&#xff08;不畅销产品&#xff09;如上&#xff0c;精品类产品占比第一&#xff0c;达到66.7%&#xff0c;其次是香化类产品&#x…

Python使用设计模式中的建筑模式将数据写入Excel且满足条件内容标红

对于这个任务&#xff0c;适合使用"Builder"设计模式。Builder模式的主要目的是将对象的构建与其表示分离&#xff0c;以便相同的构建过程可以创建不同的表示。在这个情况下&#xff0c;我们需要一个构建器来逐行构建Excel表格&#xff0c;并根据给定的数据添加相应的…

JAVA系列 小白入门参考资料 继承

目录 1. 为什么需要继承 2. 继承的概念 3. 继承的语法 4. 父类成员访问 4.1 子类中访问父类的成员变量 1. 子类和父类不存在同名成员变量 2. 子类和父类成员变量同名 4.2 子类中访问父类的成员方法 1. 成员方法名字不同 2. 成员方法名字相同 ​5. super关键字 …

golang beego结合wire依赖注入及自动路由

1 安装wire 1.1 通过命令直接安装 go install github.com/google/wire/cmd/wirelatest 1.2 通过go get方式安装 go get github.com/google/wire/cmd/wire进入目录编译 cd C:\Users\leell\go\pkg\mod\github.com\google\wirev0.6.0\cmd\wire go build 然后将wire.exe移动到…

万兆以太网MAC设计(12)万兆UDP协议栈上板与主机网卡通信

文章目录 一、设置IP以及MAC二、上板效果2.1、板卡与主机数据回环测试2.2、板卡满带宽发送数据 一、设置IP以及MAC 顶层模块设置源MAC地址 module XC7Z100_Top#(parameter P_SRC_MAC 48h01_02_03_04_05_06,parameter P_DST_MAC 48hff_ff_ff_ff_ff_ff )(input …

【Docker】docker compose服务编排

docker compose 简介 Dockerfile模板文件可以定义一个单独的应用容器&#xff0c;如果需要定义多个容器就需要服务编排。 docker swarm&#xff08;管理跨节点&#xff09; Dockerfile可以让用户管理一个单独的应用容器&#xff1b;而Compose则允许用户在一个模板&#xff08…

某赛通电子文档安全管理系统 多处 SQL注入漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

微信小程序与web-view网页进行通信的尝试

首先&#xff0c;微信小程序向web-view传递数据一般通过地址栏传参的形式&#xff08;给src赋值或者修改hash&#xff09;&#xff0c;这样一般就已经能够满足实际开发需求了&#xff0c;所以这里主要探讨web-view向微信小程序传参。下面&#xff0c;我们从官方文档入手&#x…

C语言:项目实践(贪吃蛇)

前言&#xff1a; 相信大家都玩过贪吃蛇这款游戏吧&#xff0c;贪吃蛇是久负盛名的游戏&#xff0c;它也和俄罗斯方块&#xff0c;扫雷等游戏位列经典游戏的行列&#xff0c;那贪吃蛇到底是怎么实现的呢&#xff1f; 今天&#xff0c;我就用C语言带着大家一起来实现一下这款游戏…

Linux第十五章

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

Three.js杂记(十五)—— 汽车展览(下)

在上一篇文章Three.js杂记&#xff08;十四&#xff09;—— 汽车展览上 - 掘金 (juejin.cn)中主要对切换相机不同位置和鼠标拖拽移动相机焦点做了简单的应用。 那么现在聊聊该如何实现汽车模型自带的三种动画展示了&#xff0c;实际上可以是两种汽车前后盖打开和汽车4车门打开…

网络安全之密码学技术

文章目录 网络信息安全的概念数据加密|解密概念密码学概论密码学分类古典密码学现代密码学 现代密码学的相关概念对称加密算法对称加密算法—DES对称加密算法—3DES对称加密算法—AES对称加密算法—IDEA 非对称加密算法非对称加密算法—RSA非对称加密算法—ElGamal非对称加密算…