图:BFS(深度优先搜索)图解分析代码实现
文章目录
- 一、介绍
- 二、图的建立
- 2.1建立图类
- 2.2建立图
- 三、BFS
- 3.1图解:
- 3.2代码
- 四、DFS和BFS完整代码
一、介绍
图的DFS(深度优先搜索)与BFS(广度优先搜索)是图的两种遍历方式。
主要区别在于当到达图中的一个顶点后,DFS直接到达其中的一个(未遍历过的)顶点,之后再以这个新的顶点为基点重复上面的操作;而BFS到达图中的一个顶点后,会先遍历顶点周围的所有(未遍历过的)顶点,然后在以其中的一个顶点为基点,重复上面的操作。
举个简单的例子:
如果分别用DFS和BFS进行遍历(以A为起点):
DFS:A B D E C (一条路走到头)
BFS:A B C D E (先把A的周围走完,接着走完B和C的周围)
这篇文章将进行BFS的分析,前一篇文章分析DFS:link
二、图的建立
2.1建立图类
- 使用邻接矩阵保存图的信息。
- 为了给每个顶点起名字,使用了两组map集合使顶点的名字与邻接矩阵的数字一一对应。
- 用boolean型数组记录某节点是否被访问过。
代码:
class graph{int vertexNum;//顶点数int edgeNum;//边数int[][] adjacentMatrix;//邻接矩阵boolean[] isVisited;//各顶点是否被访问Map<Character,Integer> nameToNum;Map<Integer,Character> numToName;int index;//顶点名称的下标//构造函数graph(int vertexnum, int edgenum){vertexNum = vertexnum;edgeNum = edgenum;adjacentMatrix = new int[vertexNum][vertexNum];nameToNum = new HashMap<>();numToName = new HashMap<>();isVisited = new boolean[vertexnum];}//顶点名称public void addVertexName(char vertex){nameToNum.put(vertex,index);index++;}//反转顶点和其索引的对应关系public void invertNameToNum(){Set<Character> chs = nameToNum.keySet();for (Character c : chs) {numToName.put(nameToNum.get(c),c);}}//打印两个mappublic void printMap(){System.out.println("name to num:");Set<Character> chs = nameToNum.keySet();for (Character c : chs) {System.out.println(c + "->" + nameToNum.get(c));}System.out.println();System.out.println("num to name:");Set<Integer> ins = numToName.keySet();for (Integer in : ins) {System.out.println(in+"->"+ numToName.get(in));}}//添加边public void addEdge(char vertex1, char vertex2, int weight){adjacentMatrix[nameToNum.get(vertex1)][nameToNum.get(vertex2)] = weight;adjacentMatrix[nameToNum.get(vertex2)][nameToNum.get(vertex1)] = weight;}//打印邻接矩阵public void printAdjacentMatrix(){for (int[] am : adjacentMatrix) {for (int i : am) {System.out.print(i + " ");}System.out.println();}}}
2.2建立图
以下面的图为例,建立图结构。
main方法中的代码:
public static void main(String[] args) {//while (true) {System.out.println("请输入顶点数:");Scanner sc = new Scanner(System.in);int vertexNum = sc.nextInt();System.out.println("请输入边数:");int edgeNum = sc.nextInt();graph gr = new graph(vertexNum, edgeNum);for (int i = 0; i < vertexNum; i++) {System.out.println("请输入第" + i + "个顶点的名称:");gr.addVertexName(sc.next().charAt(0));//字符串的第一个字符存入}gr.invertNameToNum();for (int i = 0; i < edgeNum; i++) {System.out.println("请输入第" + i + "条边(name1 name2 weight):");gr.addEdge(sc.next().charAt(0), sc.next().charAt(0), 1);//无向图权重为1,不用输入}gr.printAdjacentMatrix();}
依次输入相关信息:
出来的邻接矩阵:
三、BFS
- BFS方法使用队列进行遍历。
- 先将出发点压入队列,之后将其周围的点压入队列。
- 出队列的过程就是遍历输出的过程。
- 每次出队列时,将其周围的(未遍历过的)顶点都入队列。
- 当队列中没有元素了,就表明遍历完成。
3.1图解:
以A为起始点,将A的周围顶点都入队列(队列=ABCD),A出队列输出A,A周围的顶点都入队列了,不用执行入队列操作。
此时队列=BCD,B出队列,输出B,将B相邻顶点E入队列。
此时队列=BCDE,C出队列,输出C,将C相邻顶点F入队列。
此时队列=DEF,D出队列,输出D,将D相邻顶点G入队列。
此时队列=EFG,E出队列,输出E。后面循环这个操作,依次输出E,F,G。
输出顺序为:A B C D E F G。
代码:
3.2代码
graph类中的方法。
public void BFS(){Queue<Integer> qu = new ArrayDeque<>();//创建队列qu.add(0);//从第0开始访问System.out.print(numToName.get(0)+ "->");isVisited[0] = true;while(!qu.isEmpty()){//队列是否为非空int po = qu.poll();//出队列int start = 0;while(start < vertexNum ){//将周围的顶点(未标记过的)入队列if(adjacentMatrix[po][start] != 0 && !isVisited[start]){qu.add(start);//入队列System.out.print(numToName.get(start)+"->");//输出isVisited[start] = true;//标记为访问过}start++;}}System.out.println("结束");}
结果:A->B->C->D->E->F->G->结束
四、DFS和BFS完整代码
package graph;
import java.util.*;public class BFSAndDFS {public static void main(String[] args) {System.out.println("请输入顶点数:");Scanner sc = new Scanner(System.in);int vertexNum = sc.nextInt();System.out.println("请输入边数:");int edgeNum = sc.nextInt();graph gr = new graph(vertexNum, edgeNum);for (int i = 0; i < vertexNum; i++) {System.out.println("请输入第" + i + "个顶点的名称:");gr.addVertexName(sc.next().charAt(0));//字符串的第一个字符存入}gr.invertNameToNum();for (int i = 0; i < edgeNum; i++) {System.out.println("请输入第" + i + "条边(name1 name2 weight):");gr.addEdge(sc.next().charAt(0), sc.next().charAt(0), 1);}gr.printAdjacentMatrix();gr.DFS();gr.BFS();}}class graph{int vertexNum;//顶点数int edgeNum;//边数int[][] adjacentMatrix;//邻接矩阵boolean[] isVisited;//各顶点是否被访问Map<Character,Integer> nameToNum;Map<Integer,Character> numToName;int index;//顶点名称的下标//构造函数graph(int vertexnum, int edgenum){vertexNum = vertexnum;edgeNum = edgenum;adjacentMatrix = new int[vertexNum][vertexNum];nameToNum = new HashMap<>();numToName = new HashMap<>();isVisited = new boolean[vertexnum];}//顶点名称public void addVertexName(char vertex){nameToNum.put(vertex,index);index++;}//反转顶点和其索引的对应关系public void invertNameToNum(){Set<Character> chs = nameToNum.keySet();for (Character c : chs) {numToName.put(nameToNum.get(c),c);}}//打印两个mappublic void printMap(){System.out.println("name to num:");Set<Character> chs = nameToNum.keySet();for (Character c : chs) {System.out.println(c + "->" + nameToNum.get(c));}System.out.println();System.out.println("num to name:");Set<Integer> ins = numToName.keySet();for (Integer in : ins) {System.out.println(in+"->"+ numToName.get(in));}}//添加边public void addEdge(char vertex1, char vertex2, int weight){adjacentMatrix[nameToNum.get(vertex1)][nameToNum.get(vertex2)] = weight;adjacentMatrix[nameToNum.get(vertex2)][nameToNum.get(vertex1)] = weight;}//打印邻接矩阵public void printAdjacentMatrix(){for (int[] am : adjacentMatrix) {for (int i : am) {System.out.print(i + " ");}System.out.println();}}/*** 深度优先遍历* @param index 顶点的索引*/public void DFS(int index){System.out.print(numToName.get(index) + "->");isVisited[index] = true;int start = 0;while( start < vertexNum && (adjacentMatrix[index][start] == 0||(adjacentMatrix[index][start] != 0 && isVisited[start]))){start++;}if(start > vertexNum - 1){return;}DFS(start);}public void DFS(){for (int i = 0; i < vertexNum; i++) {if(!isVisited[i]){DFS(i);}}System.out.println("结束");for (int i = 0; i < isVisited.length; i++) {isVisited[i] = false;}}public void BFS(){Queue<Integer> qu = new ArrayDeque<>();//创建队列qu.add(0);//从第0开始访问System.out.print(numToName.get(0)+ "->");isVisited[0] = true;while(!qu.isEmpty()){int po = qu.poll();int start = 0;while(start < vertexNum ){if(adjacentMatrix[po][start] != 0 && !isVisited[start]){qu.add(start);System.out.print(numToName.get(start)+"->");isVisited[start] = true;}start++;}}System.out.println("结束");}}
图:BFS(深度优先搜索)图解分析代码实现相关推荐
- 图:DFS(深度优先搜索)图解分析代码实现
文章目录 一.简介 二.图的建立 2.1建立图类 2.2建立图 三.DFS 3.1图解 3.2代码 一.简介 图的DFS(深度优先搜索)与BFS(广度优先搜索)是图的两种遍历方式. 主要区别在于当到达 ...
- 图的深度搜索c语言,求图的深度优先搜索!该怎么处理
当前位置:我的异常网» C语言 » 求图的深度优先搜索!该怎么处理 求图的深度优先搜索!该怎么处理 www.myexceptions.net 网友分享于:2013-03-16 浏览:12次 求图的 ...
- 【数据结构】图的深度优先搜索
图的深度优先搜索类似于树的深度优先搜索.不同的是,图中可能包括循环,即我们有可能重复访问节点.为了避免访问已经访问过的节点,我们要使用一个布尔变量的数组. 例如,在下图中,我们从节点2开始访问.当访问 ...
- 图的深度优先搜索(DFS)
今天又复习了图的深度优先搜索,深深感觉了深搜就是外挂,岂止是外挂,简直就是外挂,动态规划做不出来的,深搜搜出来了,贪心贪不出来的深搜搜出来了,连并查集,拓扑排序做不出来的,深搜都做出来了,很遗憾以前深 ...
- 图的深度优先搜索及拓扑排序
本文将介绍图的深度优先搜索,并实现基于深度优先搜索的拓扑排序(拓扑排序适用于有向无环图,下面详细介绍). 1. 图的深度优先遍历要解决的问题 图的深度优先搜索与树的深度优先搜索类似,但是对图进行深度优 ...
- 图的深度优先搜索-递归
图的深度优先搜索的过程: (1)从图的某个顶点V出发,访问V. (2)找出刚访问过的顶点的第一个未被访问的邻接点,访问该顶点.以该顶点为新顶点,重复此步骤,直到 刚顶点没有未bedi被访问的邻接点为止 ...
- 采用邻接矩阵形式存储图,进行图的深度优先搜索并输出结果。
内容: 采用邻接矩阵形式存储图,进行图的深度优先搜索并输出结果. 步骤: 算法分析 本题需要利用邻接矩阵的形式存储图,并对图进行深度优先搜索并输出结果.大体上可以分为两个部分,一是采用邻接矩阵的方式存 ...
- 邻接矩阵实现图的深度优先搜索(1)
邻接矩阵实现图的深度优先搜索(1) /************************************************************/ /****************** ...
- 数据结构与算法—图论之dfs、bfs(深度优先搜索、宽度优先搜索)
文章目录 前言 邻接矩阵和邻接表 深度优先搜索(dfs) 宽度(广度)优先搜索(bfs) 总结与比较 前言 在有向图和无向图中,如果节点之间无权值或者权值相等,那么dfs和bfs时常出现在日常算法中. ...
最新文章
- 使用TensorFlow进行机器学习即服务
- Xamarin Android设置界面提示类型错误
- 列字段通用excel导入修改版
- Codeforces Round #661 (Div. 3)
- HOW-TO:带有MySQL的JEE应用程序中具有集群功能的Quartz Scheduler
- 软件或jar包等名字里的GA意思
- 彻底解决Spring MVC 中文乱码 问题
- 设计模式的C语言应用-导言-第一章
- Python——文件操作3——文件修改
- MySql Binlog初识
- Vue学习计划基础笔记(六) - 组件基础
- 手机计算机键盘技巧,【盲打计算器】看似简单,你不一定会的小技巧
- Xshell5 注册码 ,Xftp5 注册码,Xmanager5注册码
- 装修软件平台开发的优势
- excel生成随机数 / random number in excel
- https封装类,支持get/post请求
- cloudstack GuestNetwork Ingress-Egress rule
- Geany的所有主题文件
- 华硕笔记本刷BIOS
- MySQL笔记--2、3、4、5