这是《算法图解》第六篇读书笔记,涉及的主要内容为图结构、深度优先搜索和广度优先搜索。 1.图 1.1图的概述 图(graph)是一种基本的数据结构,它由点和边构成。 以下是邻接列表的实现方式: G=[ [1,5], [2,3,5], [3], [4,5], [5], [] ] 以下是邻接字典的实现方式: G={ 'a':{'b','f'}, 'b':{'c','d' 其思路是先搜索每一层次的节点,搜索完毕后,再搜索下一层次的节点。 u='e' path=[u] while P[u] is not None: path.append(P[u]) u=P[u] path.reverse() print(path) 3. 深度优先搜索 深度优先搜索(depth first search)是搜索图时常用的另一种方法。
简介 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。 当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。 属于盲目搜索。 实现方法 首先将根节点放入队列中。 从队列中取出第一个节点,并检验它是否为目标: 如果找到目标,则结束搜寻并回传结果。 否则将它某一个尚未检验过的直接子节点加入队列中。
深度优先搜索,简称dfs。我们可以将它跟递归联合在一起。 dfs与递归 先回顾一下递归。 == 1 || n == 2){ return 1; } return fib(n - 1) + fib(n - 2); } 以上递归实现斐波那契实际上就是按照深度优先的方式进行搜索 注意:这里的搜索指的是一种穷举方式,把可行的方案都列举出来,不断尝试,直到找到问题的解。 ? 以上即为Fib(5)的计算过程,我们发现实际上对应着一棵树,这棵树被称为搜索树。 深度优先搜索与递归的区别: 深度优先搜索是一种算法,更注重思想。 递归是一种基于编程语言的实现方式。 深度优先搜索可以使用递归实现!当然也就存在非递归的的方式实现搜索。 dfs与迷宫游戏 ? 代码实现: 首先要处理好边界条件,即什么时候搜索结束。
终结状态可能是成功解决了问题,那么我们发现了问题的一个解;也可能是没有解决问题,但是后面无路可走了,那么说明说我们之前做的决策有错误 深度优先搜索可以用来遍历所有选择,找到所有的终结状态,从而找到所有的解 例如f1=2表示从1滑动到3需要先经过2;特别的fi=0表示从i到j没有限制 这个f数组是这样的,其余的f值是0: f[1][3] = f[3][1] = 2; f[1][7] = f[7][1] = 4; f[1][9] = f[9][1] = f[2][8] = f[8][2] = f[4][6] = f[6][4] = f[3][7] = f[7][3] = 5; f[3][9] = f[9 ][3] = 6; f[7][9] = f[9][7] = 8; 然后就是深度优先搜索的过程。 [4] = f[3][7] = f[7][3] = 5; f[3][9] = f[9][3] = 6; f[7][9] = f[9][7] = 8; cin >> t;
例题 输入一棵二叉树求该树的深度。 从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。 这里获取一棵二叉树的深度,可以是递归的方法,属于DFS(深度优先搜索);另一种方法是按照层次遍历,属于BFS(广度优先搜索)。 DFS(深度搜索) 通过遍历的方式进行深度搜索 可以是自底向上汇总搜索结果 or 自顶向下汇总搜索结果 示例代码 /* struct TreeNode { int val; struct treeQueue.push(tmp->right); } } } return resDepth; } } 记录下,深度搜索 和 广度搜索的方案。
{ printf("No Solution\n"); } } return 0; } 题目链接地址 https://www.patest.cn/contests/gplt/L3-
文章目录 一、深度优先搜索 DFS 1、深度优先搜索和广度优先搜索 2、深度优先搜索基本思想 3、深度优先搜索算法步骤 二、深度优先搜索示例 ( 理论 ) 1、第一轮递归 2、第二轮递归 3、第三轮递归 4、第四轮递归 5、第五轮递归 6、第六轮递归 7、第七轮递归 一、深度优先搜索 DFS ---- 1、深度优先搜索和广度优先搜索 图 的 遍历 就是 对 图 中的 结点 进行遍历 , 遍历 结点 有如下两种策略 : 深度优先搜索 DFS 广度优先搜索 BFS 2、深度优先搜索基本思想 " 深度优先搜索 " 英文名称是 Depth First Search , 简称 DFS ; DFS 基本思想 : 访问第一个邻接结点 深度优先搜索算法步骤 深度优先搜索算法步骤 : ① 访问初始结点 : 访问 初始结点 v , 并将该 初始结点 v 标记为 " 已访问 " ; ② 查找邻接节点 : 查找 初始结点 v 的 第一个 邻接节点 , 将 w 结点 作为 新的 初始结点 v , 从 ① 步骤开始执行 ; 如果 w 结点存在 但是 被访问了 , 那么 查找 w 结点的 下一个 邻接节点 , 转到步骤 ③ 执行 ; 二、深度优先搜索示例
深度/广度优先搜索 #1 深度优先搜索(DFS) Depth-First-Search ? 步骤 : 不到尽头不回头 从 1 开始,先找到其中一个相连的,2 被找到了 然后直接开始从 2 开始搜索,3 被找到了 然后从 3 开始搜索,4 被找到了 然后从 4 开始搜索,5 被找到了 然后从 3-4-5-6 #2 广度优先搜索(BFS) Breadth-First-Search ? 步骤 : 从 1 开始进行搜索的话 先搜索所有和 1 相连的,也就是 2 和 5 被找到了 然后再从 2 开始搜索和他相连的,也就是 3 被找到了 然后从 5 搜,也就是 4 被找到了 然后从 3 开始搜索,4 被找到了,但是 4 之前已经被 5 找到了,所以忽略掉就行 然后 3 开始搜索,忽略 4 所以啥都没搜到,然后从 4 开始,6 被找到了 1-2-5-3-4-6 #3 算法题 #3.1
return false; } } //检查小矩形 for (int l = (i / 3) * 3; l < (i / 3 + 1) * 3; l++) { for (int m = (j / 3) * 3; m < (j / 3 + 1) * 3; m++) {
深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次. 算法: 1、构造一个有根构成的单元素栈S; 2、If Top(S) 是目标节点 Then 停止; 3、Pop(S), 把Top(S)的所有子节点压入栈顶; 4、If S空 Then 失败 Else goto
深度优先搜索(DFS) 深度优先搜索,是从起点v0开始,优先往下v1,v2级搜索下去,同样的举例子: 假设有一个这样的文件夹: ? 深度优先搜索 深度优先搜索的做法为: 1:保存v0级别的所有文件,1,2,3,4,5,测试文本01.txt,测试文本02.txt, 2:先遍历v0级别的目录1,判断为目录,而不是目标文件 3:保存目录 深度优先搜索的做法是,从一个起点开始,一直遍历下去,直到满足条件或者没有数据遍历,则开始第二个点开始遍历,直到最后一个vo级数据遍历完毕 广度优先搜索和深度优先搜索 现在我们已经知道了广度优先搜索以及深度优先搜索的搜索步骤 3:创建一个数组,用于记录已经遍历的文件夹(通用写法,当你的v2级文件夹,有一个是v0级的快捷方式的时候,需要判断一下是否已经遍历过了,如果有就不再遍历) 由于深度优先搜索的特性,需要通过一个全局的结果集数组保存结果值 在调用一个文件夹的时候,去获取他的子级并且开始下一次循环 3:根据结果集判断搜索任务是否完成 4:判断任务数据 判断当前数据是否已经遍历过,是否跳过 php实现如下: <?
return false; } } //检查小矩形 for (int l = (i / 3) * 3; l < (i / 3 + 1) * 3; l++) { for (int m = (j / 3) * 3; m < (j / 3 + 1) * 3; m++) {
分析:我们可以先将问题形象化,假如有编号为1、2、3的3张扑克牌和编号为1、2、3的3个盒子,现在需要将这3张扑克牌分别放到3个盒子里面,并且每个盒子有且只能放一张扑克牌。 (3)最后一个待解决的问题:什么时候该输出一个满足要求的序列? 刚才例子的代码虽然不超过20行,却饱含深度优先搜索(Depth First Search,DFS)的基本模型。 理解深度优先搜索的关键在于解决“当下该如何做”(==下一步该怎么做)。 下面的代码就是深度优先搜索的基本模型: void dfs(int step) { //判断边界 for(i=1;i<=n;i++) //尝试每一种可能 { } return; } int main() { dfs(1); printf("total=%d",total/2); return 0; } 五、感受 深度优先搜索
图有两种最基本的搜索算法,一种是深度优先搜索,另一种是广度优先搜索。本节先介绍深度优先搜索。 一、基本思想 深度优先遍历图的方法是,从图中某顶点v出发: 1 访问顶点v; 2 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问; 3 若此时图中尚有顶点未被访问 ,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。 二、例子 有一个图如下,求深度优先搜索顺序。 ? 由上面的15个步骤可知,深度搜索遍历的顺序为:1,2,4,8,5,3,6,7。
从起点出发,走过的点做标记,发现没有走过的点,就随意挑一个往前走,走不了就回退,此种路径搜索策略就称为“深度优先搜索(Depth First Search)”。 其实称为“远度优先搜索”更容易理解。因为这种策略能往前走一步就往前走一步,总是试图走的更远,所谓远近(深度),其实是以距离起点来衡量的。 { cout<<depth[i]<<endl; } } } //深度优先遍历图上所有节点
总结 本系列为C++算法学习系列,会介绍 算法概念与描述,入门算法,基础算法,数值处理算法,排序算法,搜索算法,图论算法, 动态规划等相关内容。本文为搜索算法部分。 大纲要求 【 5 】深度优先搜索 【 5 】广度优先搜索 搜索算法-深度优先搜索 例1:全排列 现假设有n个整数,分别是1~n,现在将这n个数进行排列,每一个整数只能并且一定要出现一次,求它们的全排列 '; dfs(0); return 0; } //dfs与递归类似 搜索算法-广度优先搜索 在深度优先搜索算法中,是深度越大的结点越先得到扩展。 如果在搜索中把算法改为按结点的层次进行搜索,本层的结点没有搜索处理完时,不能对下层结点进行处理,即深度越小的结点越先得到扩展,也就是说先产生的结点先得以扩展处理,这种搜索算法称为广度优先搜索法。
深度优先搜索 深度优先搜索(DFS)每次沿着路径到达不能再前进时,退回到最近的岔道口向下继续遍历。换句话说每次路径不可达时,代表一条完整路径形成。
DFS(深度优先搜索) 深度优先搜索(Depth First Search,DFS)是十分常见的图搜索方法之一。 深度优先搜索会沿着一条路径一直搜索下去,在无法搜索时,回退到刚刚访问过的节点。深搜优先搜索的本质上就是持续搜索,遍历了所有可能的情况。DFS搜索的流程是一个树的形式,每次一条路走到低。 } public static void DFS(int depth, String ans, int n) { if (depth == n) {//深度等于n时就输出 ; } public static void DFS(int depth, String ans, int n) { if (depth == n) {//深度等于n时就输出 ) { DFS(0, "");//从0层开始 } public static void DFS(int depth, String binary) {//depth为深度
前言 ---- 广度优先搜索和深度优先搜索都是对图进行搜索的算法 广度优先搜索 广度优先搜索广泛搜索子节点,将其子节点放进候选节点中;操做候选节点时是按顺序取出候选节点,因此使用队列存储候选节点。 关于队列的实现可参考队列的实现 声明广度优先搜索函数,参数为要搜索的树形图和要查找的节点 实例化队列,声明目标节点的深度,初始化0 遍历队列 获取队列第一个元素,判断是否和目标节点相等,相等返回深度 深度优先搜索 深度优先搜索将当前节点的直接子节点作为候选节点;操作候选节点时,采用最后加入的子节点,因此使用栈存储候选顶点;栈的实现 声明深度优先搜索函数,参数为要搜索的树形图和要查找的节点 数组模拟栈 //子节点组成的数组翻转,压栈 stack.push(...[...stack.children].reverse()) } return false } } 广度优先搜索和深度优先搜索的区别 深度优先搜索:选择最新成为候补的顶点,沿着一条路径搜索到底 广度优先搜索:选择最早成为候补的顶点,沿着边搜索
图的深度优先遍历类似于树的前序遍历。采用的搜索方法的特点是尽可能先对纵深方向进行搜索。这种搜索方法称为深度优先搜索(Depth-First Search)。 3、深度优先遍历的递归算法 (1)深度优先遍历算法 typedef enum{FALSE,TRUE}Boolean;//FALSE为0,TRUE为1 Boolean visited[MaxVertexNum } }//DFS (3)邻接矩阵表示的深度优先搜索算法 void DFSM(MGraph *G,int i) { //以vi为出发点对邻接矩阵表示的图G进行DFS搜索,设邻接矩阵是0,l 3)栈在深度优先遍历算法中的作用 深度优先遍历过程中,后访问的顶点其邻接点被先访问,故在递归调用过程中使用栈(系统运行时刻栈)来保存已访问的顶点。 4) (2, 4) (2, 3) (2, 2) (2, 1) (2, 0) (1, 0) (0, 0) 其实仍然可以像例 12.3 “用深度优先搜索解迷宫问题”一样用predecessor数组表示每个点的前趋