生成图-深度优先搜索/宽度优先搜索
问题提出:
考虑如下图所示的简单图所表示的缅因州的道路系统。在冬天里保持道路通路通畅的唯一方式就是经常扫雪。高速公路部分希望只扫尽可能少的道路上的雪,而确保总是存在连接任何两个乡镇的干净道路。如何才能做到这点呢?
最简单的方式就是一个哈密顿图,形成一个回路,这当然可以。假设一个回路有n个点,则会有n条边;但对于树,n个点对应n-1条边,所以我可以去寻找一颗树即可。有人说那我们不形成一个圈不就是n-1了么?同学,一条线也是树的一种。将问题剥离成一个数学问题就是,如何从一个图中找到树。树有什么特征呢?这就要问什么叫做树了,树就是每对顶点之间存在唯一简单通路的无向图。所以针对这个图中的每对顶点之间也应该是有通路的,即简单连通图。这里有两种方法,即深度优先搜索和宽度优先搜索。
1.深度优先搜索
//d为图的邻近矩阵,p为所生成树的邻近矩阵,
//n为图中点的个数,w为要遍历的顶点
void visit(int **d,int **p,int *T,int n,int w)
{cout<<w<<" ";//输出遍历的点T[w]=1;//已经遍历的点,要加进新增的树中for(int i=0;i<n;i++){//遍历每个点的所有状态,即分支if(d[w][i]==1&&T[i]!=1){//如果有通路,且点不在树中,则记录边,同时访问该分支p[w][i]=1;//记录边visit(d,p,T,n,i);//访问该分支}}
}void DFS(int **d,int **p,int n)
{int *T=new int[n];//建立新建树的顶点集memset(T,0,sizeof(int)*n);visit(d,p,T,n,0);//第一个作为初始值,即从第一个点开始遍历
}
即结果为:
void BFS(int **d,int **p,int n)
{int v;int *T=new int[n];//保存已经生成树的节点int *L=new int[n];//保存每一个树顶点的邻居,memset(T,0,sizeof(int)*n);memset(L,0,sizeof(int)*n);int iL=1;//L的初始长度为1T[0]=1;//只包含顶点0的树L[0]=1;//把初始点0放入尚未处理顶点的表L中while(iL!=0){//如果没有要处理的点,即尚未处理的点没了,则停止v=0;while(v<n&&!L[v++]);//寻找尚未处理顶点,由于索引结果多了个1,后面要减掉L[--v]=0;iL--;//删除L中所寻找的点,表示即将寻找此点的所有邻点cout<<v<<" ";//输出即将处理的点for(int i=0;i<n;i++){if(d[v][i]==1&&T[i]!=1&&L[i]!=1){//如果v与i之间相连,且v不在树T和尚未处理集合L中,则记录下来,作尚未处理的点p[v][i]=1;//记录边T[i]=1;//加入到树中L[i]=1;//加入尚未处理点集合L中,等待处理iL++;//L长度要加1}}}
}
运行结果:
3.网络解释:
3.1
广度优先搜索算法,一般需存储产生的所有结点,占用的存储空间要比深度优先搜索大得多,因此,程序设计中,必须考虑溢出和节省内存空间的问题。但广度优先搜索法一般无回溯操作,即入栈和出栈的操作,所以运行速度比深度优先搜索要快些
3.2
3.3
(1)从上面几个实例看出,可以用深度优先搜索的方法处理的题目是各种各样的。有的搜索深度是已知和固定的,如例题4—4、4—5、4—6;有的是未知的,如例题4—7、例题4—8,有的搜索深度是有限制的,但达到目标的深度是不定的。但也看到,无论问题的内容和性质以及求解要求如何不同,但它们的程序结构都是相同的,即都是深度优先算法(一)和深度优先算法(二)中描述的算法结构,不相同的仅仅是存储节点数据结构和产生规则以及输出要求。
(2)深度优先搜索法有递归以及非递归两种设计方法。一般的,当搜索深度较小、问题递归形式较明显时,用递归方法设计的较好,它可以使得程序结构更简捷易懂。但当搜索深度较大时,如例题4—5、4—6,当数据量较大时,由于系统堆栈容量的限制,递归易产生溢出,用非递归方法设计比较好。
(3)深度优先搜索方法有广义和狭义两种理解。广义的理解是,只要最新产生的节点(即深度最大的节点)先进行扩展的方法,就称为深度优先搜索方法。在这种理解情况下,深度优先搜索算法有全部保留和不全部保留产生的节点的两种情况。而狭义的理解是,仅仅只保留全部产生节点的算法。本书取前一种广义的理解。不保留全部节点的算法属于一般的回溯算法范畴。保留全部节点的算法,实际上是在数据库中产生一个节点之间的搜索树,因此也属于图搜索算法的范畴。
(4)不保留全部节点的深度优先搜索法,由于把扩展完的节点从数据库中弹出删除,这样,•一般在数据库中存储的节点数就是深度值,因此它占用的空间较少。
所以,当搜索树的节点较多,用其他方法易产生内存溢出时,深度优先搜索法不失为一种有效的算法。
(5)从输出结果可看出,深度优先找到的第一个解并不一定是最优解。例如例题4—8得最优解COST=13,但第一个解却是COST=17。
如果要求出最优解的话,一种方法将是后面要介绍到的动态规划法,另一种方法是修改原算法:把原输出过程的地方改为记录过程,即记录达到当前目标的路径和相应的路程值,并与前面已记录的值进行比较,保留其中最优的,等全部搜索完成后,才把保留的最优解输出。
广度优先搜索法的显著特点是:
(1)在产生新的子节点时,深度越小的节点越先得到扩展,即先产生它的子节点。为使算法便于实现,存放节点的数据库一般用队列的结构。
(2)无论问题性质如何不同,利用广度优先搜索法解题的基本算法是相同的。但数据库中每一节点内容、产生式规则,根据不同的问题,有不同的内容和结构。就是同一问题也可以有不同的表示方法。
(3)当节点到根节点的费用(有的数称为耗散值)和节点的深度成正比时,特别是当每一节点到根节点的费用等于深度时,用广度优先法得到的解是最优解。但如果不成正比,则得到的解不一定是最优解。这一类问题要求出最优解,一种方法是使用后面要介绍的其他方法求解,另外一种方法是改进前面深度(或广度)优先搜索方法:找到一个目标后,不是立即退出,而是记录下目标节点路径和费用。如果有多个目标节点,就加以比较,留下较优的节点。把所有可能的路径都搜索完后,才输出记录的最有路径。
(4)广度优先搜索算法,一般需存储产生的所有节点,占的存储空间要比深度优先大的多。因此程序设计中,必须考虑溢出和节省内存空间的问题。
(5)比较深度优先和广度优先两种搜索法,广度优先搜索法一般无回溯操作,即人栈和出栈的操作,所以运行速度比深度优先搜索法要快些。
总之,一般情况下,深度优先搜索法占内存少但速度较慢,广度优先搜索法占内存较多但速度较快,在距离与深度成正比的情况下能较快地求出最优解。因此在选择用那种算法时,要综合考虑,决定取舍。
生成图-深度优先搜索/宽度优先搜索相关推荐
- 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS)
广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS) 1. 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first searc ...
- 广度优先搜索 宽度优先搜索 迷宫问题 最短路径 最少操作 由近及远 队列
广度优先搜索,也叫宽度优先搜索,从开始状态,到第一次能到达的状态,再从第一次能到达的状态到下一个能到达的状态,直到探索所有可到达的状态,其时间复杂度为O(状态数×转移的方式). 广度优先搜索使用了队列 ...
- 迷宫问题 深度优先搜索 广度优先搜索 宽度优先搜索【python】
文章目录 一.实验内容 二.深度优先搜索和广度优先搜索总结 1.深度优先搜索算法 2.广度优先搜索算法 三.实验代码和用于测试的迷宫 1.实验代码 2.测试迷宫 2.1 maze1.txt 2.2 m ...
- 算法笔记01——深度优先搜索(DFS)/宽度优先搜索(BFS)
深度优先搜索(DFS) 从某个状态开始,不断地转移状态直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直至找到最终的解.深度优先搜索从最开始的状态出发,遍历所有可以到达的状态. ...
- 宽度优先搜索与深度优先搜索
宽度优先搜索算法顺序:1-2-3-4-5-6-7 深度优先搜索算法顺序:1-2-4-5-3-6-7 宽度优先搜索算法(又称广度优先搜索)BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点 ...
- 深度优先搜索与宽度优先搜索
深度优先搜索 简称:DFS 基本思路 深度优先遍历图的方法是,从图中某顶点v出发: (1)访问顶点v: (2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历:直至图中和v有路径相通的顶点都被访问 ...
- ACM算法笔记(十)深度优先搜索与宽度优先搜索
深度优先搜索 事实上,深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次. 下面 ...
- 深度优先搜索和宽度优先搜索
深度优先搜索和宽度优先搜索 bfs和dfs都是遍历图的方法.dfs是不撞南墙不回头,bfs慢慢来,一层一层来. 类型 空间(h为高度) 时间(h为高度) 采用的数据结构 特点 DFS O(h) O( ...
- 八数码宽度优先搜索python代码_图之遍历--广度优先遍历
何为广度优先遍历呢? 广度优先遍历(BFS),又叫宽度优先搜索或横向优先搜索,是从根结点开始沿着树的宽度搜索遍历,将离根节点最近的节点先遍历出来,在继续深挖下去. 基本思想是: 1.从图中某个顶点V0 ...
最新文章
- [置顶] 面向业务开发应用
- 如何让Git适应敏捷开发流程?
- bash: _upvars: `-a2‘: invalid number specifier bash: /dev/null: 权限不够 bas
- 小程序背景图片从服务器获取,小程序之背景图片的加载
- 几种常见的分布及其性质
- python爬虫反爬策略_用Python语言做爬虫有哪些策略可以对抗反爬虫?
- Max Points on a Line@LeetCode
- C#反射获取 所有字段 及 私有字段
- 计算机英语 1000字论文范文,英语论文格式写作 1000字论文格式-免费论文范文
- 谈谈RJ45线序的打法及口诀
- CRYPTO buuctf 摩斯
- Oracle 数据库表空间容量调整(表空间缩容脚本)脚本
- 节卡JAKA机械臂培训笔记(偏入门)
- MaxCompute(ODPS)一对多连表时实现多行过滤(同样适用于MySQL)
- 零碎知识点之一:循环平稳信号
- 【荐藏】代谢组学分析系列
- 锂离子电池--SEI膜
- 牛客网SQL大厂真题二刷小白白话总结(二)用户增长场景(某度信息流)
- 产品经理与项目经理的区别?
- Windows 10下无法安装 CAD 2013/2014的解决方法