-
2022-03-12 22:15:54
宽度优先遍历就是从上到下,从左到右依次遍历就行。
可以使用队列来做。
先将头结点放入队列,
重复下面的行为。
{从队列中弹出一个节点,并打印。
如果弹出的节点有左节点,就将左节点放入队列中,
如果弹出的节点有右节点,就将右节点放入队列中。先左后右。
}
public static void widthPrioritySearch(NodeTwo node) { if(node==null) { return ; } Queue<NodeTwo> queue = new LinkedList<>(); queue.add(node); while(!queue.isEmpty()) { NodeTwo cur = queue.poll(); System.out.println(cur.value); if(cur.left != null) { queue.add(cur.left); } if(cur.right != null) { queue.add(cur.right); } } }
求二叉树的最大宽度:
思路:记录每一个节点所在的层,并且用一个变量记录每一层有多少个节点。
记录每一个节点所在的层最好使用的就是hash表。
public static int widthMax(NodeTwo node) { if(node==null) { return 0; } Queue<NodeTwo> queue = new LinkedList<>(); HashMap<NodeTwo,Integer> map = new HashMap<>(); //使用hash表来记录每个节点所在的层数 map.put(node, 1); int currentLevel = 1; int currentNodes = 0; int max = Integer.MIN_VALUE; queue.add(node); while(!queue.isEmpty()) { NodeTwo cur = queue.poll(); int level = map.get(cur); if(currentLevel == level) { //弹出节点所在的层数等于现在的层数, //当前层数的节点数加1 currentNodes++; }else { //如果弹出节点的层数不等于当前的层数 //那么就是这个节点是下一层的了,上一层的节点个数已经统计好了 max = Math.max(max, currentNodes); // currentLevel++; currentNodes = 1; //当前层的节点数置为1, } // System.out.println(cur.value); if(cur.left != null) { queue.add(cur.left); map.put(cur.left, map.get(cur)+1); } if(cur.right != null) { queue.add(cur.right); map.put(cur.right, map.get(cur)+1); } } //在最后一个节点弹出的时候有可能满足currentLevel == level //就不会将最后一层的节点数与最大值相比较 //所以弹出所有节点之后需要再将最后一层的节点数和最大值进行比较 return max = Math.max(max, currentNodes); }
更多相关内容 -
宽度优先搜索 算法.doc
2020-06-09 18:24:23采用宽度优先搜索算法,编程实现八数码问题的求解。初始状态和目标状态可自定;采用宽度优先搜索算法,编程实现八数码问题的求解。初始状态和目标状态可自定采用宽度优先搜索算法,编程实现八数码问题的求解。初始... -
宽度优先算法解决八数码问题实验报告.zip
2020-05-20 10:38:11本资源包括宽度优先搜索算法解决八数码问题的实验报告以及用python实现的源代码,有较详细的原理和设计思路,代码有详细的注释,适合初学者学习。 -
宽度优先算法
2019-01-08 22:07:21人工智能作业,利用python实现宽度优先BFS搜索解决八数码问题 -
宽度优先搜索
2021-01-20 11:55:56宽度优先搜索(BFS) 1.什么时候使用BFS 1.图的遍历 -层级遍历 -由点及面(连通性) -拓扑排序 2.最短路径 -仅限简单图求最短路径 ,即图中每条边的长度都是1(一样),且没有方向。 2.解树的遍历(层级遍历) ... -
八数码宽度优先搜索(加注释).txt
2020-03-22 16:17:21本源码是针对八数码问题的C语言实现方法,有较详细的注释。着重于广度搜索条件。大概就是这样吧。。。为啥这资源描述要这么多字。。。。 -
宽度优先搜索遍历算法-8.4迷宫问题
2021-01-06 20:35:11例8.4迷宫问题 如图所示,给出一个n*m的迷宫图和一个入口、一个出口 编写一个程序,打印从一条从迷宫入口到出口的路径。这里黑色方块的单元表示走不通(用-1表示),白色表示可以走(用0表示) ... -
八数码问题宽度优先搜索(Java实现)
2018-12-06 19:07:09利用Java实现人工智能的八数码问题的宽度优先算法,实现对该问题的解决 -
基于PyQt实现可视化宽度优先、深度优先、贪婪算法和 A*算法解决罗马尼亚度假问题。
2020-10-18 10:17:32分别采用:宽度优先、深度优先、贪婪算法和A*算法实现罗马尼亚度假问题。主要程序分为画布以及功能区两个部分,其中功能区又具有通过深度优先搜索算法、广度优先算法、贪婪算法、 A* 算法搜索指定节点间最短路径的... -
使用过程式,宽度优先,A算法求解八数码问题
2017-07-01 16:27:26使用过程式,宽度优先,A算法求解八数码问题 -
图的宽度优先遍历
2021-12-20 16:52:49如果可以给个三连,那真是十分感谢, 二叉树的宽度优先遍历只用到了队列,不清楚的朋友可以看看这篇文章二叉树的按层遍历。但是图还需要HashSet,因为二叉树不会有环的问题。二叉树进行宽度优先遍历的时候,一...大家好,我是一名计算机专业的大三在校生,自不量力想明年秋招进大厂BATJMZ💪💪💪。由于大学里面荒废了两年😔,所以决定从此刻开始改变。希望通过写博客记录自己学习和成长的历程;同时也能够增长见识,学习到更多的知识,遇见更多志同道合的人🤝🤝🤝。本人目前还只是个青铜,希望和我的读者朋友们可以共同进步,一起探讨。如果我的文章能够帮到你的话,那实在是我的幸运,也希望我写的博客内容能够帮助一些在编程方面有问题的朋友。在这里如果你发现我写的有哪些不对或不足之处,请您谅解。你可以及时评论或私信来告诫我,我会积极采纳改正的,我会努力提升博客文章的质量。如果可以给个三连,那真是十分感谢,🙇🙇🙇
二叉树的宽度优先遍历只用到了队列,不清楚的朋友可以看看这篇文章二叉树的按层遍历。但是图还需要HashSet,因为二叉树不会有环的问题。二叉树进行宽度优先遍历的时候,一个结点不会多次进入队列,而图有可能。所以准备一个HashSet。HashSet就是保证每个结点只进一次队列。
从某个结点出发,假设是X,离X结点最近的一层结点先遍历,再是遍历离X距离两层的结点,接着往下…但是同一层内部具体的遍历顺序没有要求。队列弹出的时候,弹出就打印,然后遍历弹出结点的所有直接邻居,没有在HashSetl里的结点才可以加入队列和HashSet。
注意:队列和HashSet是同步加入的!!!
package com.harrison.class11; import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; import com.harrison.class11.Code01_NodeEdgeGraph.Node; public class Code02_BFS { // 从node出发,进行宽度优先遍历,只需要用到点结构 public static void bfs(Node node) { if (node == null) { return; } Queue<Node> queue = new LinkedList<>(); // 在二叉树进行宽度优先遍历时不会形成环 // 但图会形成环,所以必须有个机制来确保每个结点只进一次队列 HashSet<Node> set = new HashSet<>(); queue.add(node); set.add(node); while (!queue.isEmpty()) { Node cur = queue.poll(); System.out.println(cur.value); // 遍历当前结点的所有直接后继 // 如果set中没有才加入set和队列 for (Node next : node.nexts) { if (!set.contains(next)) { set.add(next); queue.add(next); } } } } }
宽度优先遍历只需要用到点结构就可以实现,所以表示图的方式很重要。这篇文章实现图的方式就很合适,推荐大家看看——图结构的实现,从点到边再到图。
最后再总结一下,宽度优先遍历的流程:
1)利用队列实现
2)从源节点开始依次按照宽度进队列,然后弹出
3)每弹出一个点,把该节点所有没有进过队列的邻接点放入队列
4)直到队列变空
-
分别用宽度优先、深度优先、贪婪算法和A*算法求解“罗马利亚度假问题”
2015-12-08 10:04:14分别用宽度优先、深度优先、贪婪算法和 A*算法求解“ 罗马利亚度假问题 ”(即最短路径的搜索问题)。要求:分别用文件存储地图和启发函数表,用生成节点数比较几种算法在问题求解时的效率,列表给出结果。(中国... -
深度优先搜索(DFS)与宽度优先搜索(BFS)解析及例题_c语言
2022-02-08 15:47:28深度优先搜索(DFS) 宽度优先搜索(BFS) c语言解题 相关例题 部分和问题 Lake Counting问题 迷宫的最短路径深度优先搜索(DFS)
1.定义
从某个状态开始,不断地转移状态直到无法转移,然后回退到前一步状态,继续转移到其他状态,如此不断重复,直到找到最终的解。
根据深度优先搜索的特点,采用递归函数实现比较简单。
深度优先搜索(隐式地)利用了栈进行计算。2.状态转移图
3.例题
3.1 部分和问题
问题描述
给定正整数a1,a2,…,an,判断是否可以从中选出若干数,使他们的和恰好为k。
限制条件- 1<=n<=20
- -108<=ai<=108
- -108<=k<=108
样例一
输入:n=4,k=13,a={1,2,4,7}
输出:Yes
解释:13=2+4+7
样例二
输入:n=4,k=15,a={1,2,4,7}
输出:No
分析
从a1开始按顺序决定每个数加或不加,在全部n个数都决定后再判断它们的和是不是k即可。因为状态数是2n,所以复杂度为O(2n)。
代码//DFS #include<stdio.h> #define MAX_N 20 int a[MAX_N]; //存储要求和的数据 int n,k; //n代表数据个数,k代表要求出的和 //已经从前i项得到了和sum,然后对于i项之后的进行分支 int dfs(int i, int sum){ //如果前n项的都经过计算了,如何sum与k相等,返回1,否则返回0 if(i == n) return sum==k?1:0; //不加上a[i]的情况 if(dfs(i+1, sum)) return 1; //加上a[i]的情况 if(dfs(i+1, sum+a[i])) return 1; } int main(){ scanf("%d %d",&n,&k); for(int i=0; i<n; i++) scanf("%d",&a[i]); if(dfs(0,0)){ printf("Yes\n"); }else{ printf("No"); } }
3.2 Lake Counting
问题描述
有一个大小为N✖N的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出园子里总共有多少个水洼?(八连通指的是下图中相对w的*部分)
限制条件- N,M<=100
样例
输入:N=10,M=12//园子如下图('w'表示积水,'.'表示没有积水) w........ww. .www.....www ....ww...ww. .........ww. .........w.. ..w......w.. .w.w.....ww. w.w.w.....w. .w.w......w. ..w.......w.
输出:3
分析
从任意的w开始,不停地把邻接的部分用’.‘代替。1次DFS后与初始的这个w所连接的所有w就都被替换成了’.’,因此直到图中不存在w为止,总共进行DFS的次数就是答案。
代码#include<stdio.h> #define MAX_N 100 #define MAX_M 100 int N,M; char field[MAX_N][MAX_M]; //园子 //现在位置[x,y] void dfs(int x,int y){ //将现在所在位置替换为. field[x][y] = '.'; //循环遍历移动的八个方向 for(int dx = -1; dx <= 1; dx++){ for(int dy = -1; dy <= 1; dy++){ //向x方向移动dx,向y方向移动dy,移动结果为(dx,dy) int nx = x + dx, ny = y + dy; //判断(nx,ny)是不是在园子内,以及是否有积水 if(0<=nx && nx<=N && 0<=ny && ny<=M && field[nx][ny]=='w') dfs(nx,ny); } } return ; } int main(){ //输入 scanf("%d %d",&N,&M); getchar(); for(int i=0; i<N; i++){ for(int j=0; j<M; j++){ scanf("%c",&field[i][j]); } //将第一个for循环后面的换行符去掉,否则scanf默认读取换行符 getchar(); } //需要DFS的次数 int res = 0; //开始dfs for(int i=0; i<N; i++){ for(int j=0; j<M; j++){ if(field[i][j] == 'w'){ //从有w的地方开始dfs dfs(i,j); res++; } } } printf("%d\n",res); return 0; }
宽度优先搜索(BFS)
1.定义
与深度优先搜索不同之处在于搜索的顺序,宽度优先搜索总是先搜索距离初始状态近的状态。也就是说,它是按照开始状态→只需1次转移就可以到达的所有状态→只需2次就可以到达的所有状态→…这样的顺序进行搜索。对于同一个状态,宽度优先搜索只经过一次,因此时间复杂度为O(状态数✖转移的方式)。
宽度优先搜索利用了队列。搜索时首先将初始状态添加到队列里,此后从队列的最前端不断取出状态,把从该状态可以转换到的状态中尚未访问过的部分加入队列,如此反复,直至队列被取空或找到了问题的解。2.状态转移图
3.例题
3.1 迷宫的最短路径
问题描述
给定一个大小为N*M的迷宫。迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格的通道移动。请求出从起点到终点所需的最小步数(起点一定可以到达终点)。
限制条件
N,M<=100
样例
输入:N=10,M=10//迷宫如下图所示。'#','.','S','G'分别表示墙壁,通道,起点和终点。 #S######.# ......#..# .#.##.##.# .#........ ##.##.#### ....#....# .#######.# ....#..... .####.###. ....#...G#
输出:22
分析
宽度优先搜索按照距离开始状态由近及远的顺序进行搜索,因此可以很容易地用来求最短路径、最少操作之类问题的答案。
首先将起点存入队列,然后从队列中取出队头元素,遍历队头元素上下左右四个方向的通道。若其不是终点,则将此点加入队列,并存储从开始到该点的距离。然后处理下一个遍历到的点…直至队列为空。
代码#include<stdio.h> #define INF 100000000 #define MAX_N 100 #define MAX_M 100 //输入 char maze[MAX_N][MAX_M+1]; //表示迷宫的字符串的数组 int N,M; int sx,sy; //起点坐标 int gx,gy; //终点坐标 int d[MAX_N][MAX_M]; //到各个位置的最短距离的数组 //队列存储结构 int queue_x[MAX_N*MAX_M]; //存储进入队列的横坐标 int queue_y[MAX_N*MAX_M]; //储进入队列的纵坐标 int front,rear; //将坐标(x,y)加入队列queue_x,queue_y void enQueue(int x, int y){ queue_x[rear++] = x; queue_y[rear++] = y; } //将横坐标为x的移出queue_x队列 int deQueue_x(){ return queue_x[front++]; } //将纵坐标为y的移出queue_y队列 int deQueue_y(){ return queue_y[front++]; } //求从{sx,sy}到{gx,gy}的最短路径 //如果无法到达,则是INF void bfs(){ //初始化 front = 0; rear = 0; //当前遍历到的坐标 int current_x,current_y; //把所有的位置都初始化为INF for(int i=0; i<N; i++) for(int j=0; j<M; j++) d[i][j] = INF; //将起点加入队列,并把这一地点的距离设置为0 enQueue(sx,sy); d[sx][sy] = 0; //不断循环, 直到队列的长度为0 while(maze[current_x=deQueue_x()][current_y=deQueue_y()] != 'G'){ //遍历左右两面 for(int dx=-1,dy=0; dx<=1; dx+=2){ int x = current_x + dx; int y = current_y + dy; if(x>=0 && x<N && y>=0 && y<M){ //判断未出界 if((maze[x][y]=='G' || maze[x][y]=='.') && d[x][y]==INF){ d[x][y] = d[current_x][current_y] + 1; enQueue(x,y); } } } //遍历上下两面 for(int dy=-1,dx=0; dy<=1; dy+=2){ int x = current_x + dx; int y = current_y + dy; if(x>=0 && x<N && y>=0 && y<M){ //判断未出界 if((maze[x][y]=='G' || maze[x][y]=='.') && d[x][y]==INF){ d[x][y] = d[current_x][current_y] + 1; enQueue(x,y); } } } } } int main(){ scanf("%d %d",&N,&M); getchar(); for(int i=0; i<N; i++){ for(int j=0; j<M; j++){ scanf("%c",&maze[i][j]); //确定起点坐标 if(maze[i][j] == 'S'){ sx = i; sy = j; } //确定终点坐标 if(maze[i][j] == 'G'){ gx = i; gy = j; } } getchar(); } bfs(); //输出最终结果 printf("%d\n",d[gx][gy]); return 0; }
-
宽度优先搜索(BFS)详解,以及双向广搜
2022-04-15 20:39:56宽度优先搜索(BFS)与双向广搜百度百科的官方解释:宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
这是一个很难硬说就能理解的知识点,但是理解了就会觉得很简单(事实上所有知识点都是这样),配图理解BFS。
假设有这么一个图,1是起点,5是终点。
遍历时将1首先加入队列(队列就是模拟BFS用的,栈是模拟DFS用的,应用的是队列先进先出和栈先进后出的特性)
然后应用一个循环模板
while(队列不为空){ 弹出队头 遍历队头接下来的节点 将满足的节点加入队列 }
模拟while过程,将1弹出队列,遍历1相连的节点,将满足条件的加入队列(这里不设条件)
弹出队头节点3,遍历与3相连的节点,与3连接的节点进队列(这里没有与3相连的),一直是从2的左边进入(即队尾进入),所以无论如何下一次都是先遍历与2相连的节点
比如在节点4后有一个相连的6,弹出4,加入6
但下一次的队头就是5了,而不是加入的6
这就是bfs,所有起点同步进行(类似同心圆向外扩散)
这里就会出现一个问题:如果每一个入队列的节点遍历之后都能带来接下来四个满足条件的节点,那么每一次遍历,队列就会扩大四倍,有一个比较简单的方法是引用双向广搜
双向广搜:将起点和终点同时加入队列,两边同时遍历,当两个节点的下一步有相交的节点,就是最短路径或者最短时间。
优化的部分可以看此图
红色部分是单向搜索比双向搜索多出来的部分,优化空间很大,同时也优化了时间
代码模板可变性很高,下面的看个乐就行了(毕竟bfs还是用处挺广泛的)
如果用queue模板的话记住front才是队头,如果遍历是用back就错了,因为pop弹出的front
#include "iostream" #include "queue" using namespace std; struct Node{ int x; int y; }startNode,endNode; int main(){ queue<Node>bfs; bfs.push(startNode); while(!bfs.empty()){ Node tempNode=bfs.front(); int x=tempNode.x; int y=tempNode.y; bfs.pop(); Node nextNode; if(check(x+1,y)){//check是当这个条件成立时的随意一个函数,如果是迷宫 nextNode.x=x+1;//只要x+1,y这个位置不是墙壁就加入队列 nextNode.y=y; bfs.push(nextNode); } if(check(x-1,y)){ nextNode.x=x-1; nextNode.y=y; bfs.push(nextNode); } if(check(x,y-1)){ nextNode.x=x; nextNode.y=y-1; bfs.push(nextNode); } if(check(x,y+1)){ nextNode.x=x; nextNode.y=y+1; bfs.push(nextNode); } } }
-
数据结构实验3.4:以邻接表为存储结构的图的深度、宽度优先遍历.doc
2021-10-29 18:22:31数据结构实验报告 -
九章算法之宽度优先搜索(Breadth First Search, BFS)
2019-01-10 16:47:59九章算法之宽度优先搜索(Breadth First Search, BFS) 多看多思考 -
易语言宽度优先搜索算法
2020-07-23 00:17:39易语言宽度优先搜索算法源码,宽度优先搜索算法,queue_init,queue_empty,queue_push,queue_front,queue_pop,maze -
2020.10.31-笔记-深度优先与宽度优先
2020-10-31 17:31:08深度优先搜索(DFS) 从某个状态开始,不断转移状态,直到无法转移,然后退回前一步状态,继续转移到其他状态,直到找到最终的解。深度优先搜索采用递归函数实现比较简单。 例 给定整数a[1],a[2],…,a[n],判断是否... -
算法练习——宽度优先搜索算法 BFS
2021-12-15 22:16:48宽度优先搜索算法 BFS 主要应用:二叉树搜索或者图搜索 主要思想:层层递进,一层一层遍历 和DFS(深度优先)差别: DFS侧重“分支” BFS侧重“层” 基本实现思想: (1)顶点v入队列。 (2)当队列非空时则继续执行... -
宽度优先算法求解八数码问题
2022-03-16 13:59:40原则:优先扩展深度浅的节点 思路:从根节点(起始节点)开始按层进行搜索,即按层来扩展节点。 按层扩展节点指前一层的节点扩展完毕后才进行下一层节点的扩展,依次迭代,直到到达目标节点为止。 -> 空格的... -
9:图的宽度优先搜索BSF
2019-04-22 01:08:07NULL 博文链接:https://iluoxuan.iteye.com/blog/1936926 -
宽度优先搜索解决八数码问题
2021-04-12 23:28:42宽度优先搜索解决八数码问题 解八数码问题:任意输入两个九宫格作为初始状态和目标状态,用宽度优先搜索求解。#include#include#include#include#includeusing namespace std;class NineNode{public: int nine[3][3]... -
广度优先搜索 宽度优先搜索 迷宫问题 最短路径 最少操作 由近及远 队列
2022-02-06 18:08:16广度优先搜索,也叫宽度优先搜索,从开始状态,到第一次能到达的状态,再从第一次能到达的状态到下一个能到达的状态,直到探索所有可到达的状态,其时间复杂度为O(状态数×转移的方式)。 广度优先搜索使用了队列的... -
educoder数据结构与算法 图 第1关:实现图的宽度优先遍历
2021-12-09 15:55:57注意遵守约定:编号小的优先入队列。 相关知识 图 2 给出了对图 1 的无向图的存储结构图:每个顶点的名称由一个字符串描述,所有字符串的起始地址组织为一个数组,数组的起始地址为vetex;顶点的相邻关系保存... -
宽度优先遍历Or宽度优先搜索详解
2018-08-13 17:51:10宽度优先搜索(BFS, Breadth First Search)是一个针对图和树的遍历算法。发明于上世纪50年代末60年代初,最初用于解决迷宫最短路径和网络路由等问题。 对于下面的树而言,BFS方法首先从根节点1开始,其搜索节点顺序... -
宽度优先搜索算法
2020-10-12 20:24:15宽度优先搜索算法算法简介实战练习 算法简介 宽度优先搜索又称广度优先搜索或横向优先搜索。该算法是一种图形搜索算法,该算法是从起点开始搜索然后一层一层的向下搜索,如果找到目标或者搜索完了全部的节点则算法... -
广度优先搜索 / 宽度优先搜索 (Breadth First Search,BFS) - 层层递进
2020-05-21 01:02:21广度优先搜索 / 宽度优先搜索 (Breadth First Search,BFS) - 层层递进 深度优先搜索方法可用于解决从迷宫起点开始寻找一条通往迷宫中目标位置最短路径的问题。广度优先搜索 / 宽度优先搜索 (Breadth First Search,... -
宽度优先搜索(BFS)之习题分析
2021-01-06 20:43:52宽度优先搜索之习题分析一、宽度优先搜索的概念二、小岛问题(一)、题目需求(二)、解法(三)、代码分析三、单词梯(一)、题目需求(二)、解法(三)、代码分析 一、宽度优先搜索的概念 广度优先搜索(也称...