文章目录

  • 一、介绍
  • 二、图的建立
    • 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(深度优先搜索)图解分析代码实现相关推荐

  1. 图:DFS(深度优先搜索)图解分析代码实现

    文章目录 一.简介 二.图的建立 2.1建立图类 2.2建立图 三.DFS 3.1图解 3.2代码 一.简介 图的DFS(深度优先搜索)与BFS(广度优先搜索)是图的两种遍历方式. 主要区别在于当到达 ...

  2. 图的深度搜索c语言,求图的深度优先搜索!该怎么处理

    当前位置:我的异常网» C语言 » 求图的深度优先搜索!该怎么处理 求图的深度优先搜索!该怎么处理 www.myexceptions.net  网友分享于:2013-03-16  浏览:12次 求图的 ...

  3. 【数据结构】图的深度优先搜索

    图的深度优先搜索类似于树的深度优先搜索.不同的是,图中可能包括循环,即我们有可能重复访问节点.为了避免访问已经访问过的节点,我们要使用一个布尔变量的数组. 例如,在下图中,我们从节点2开始访问.当访问 ...

  4. 图的深度优先搜索(DFS)

    今天又复习了图的深度优先搜索,深深感觉了深搜就是外挂,岂止是外挂,简直就是外挂,动态规划做不出来的,深搜搜出来了,贪心贪不出来的深搜搜出来了,连并查集,拓扑排序做不出来的,深搜都做出来了,很遗憾以前深 ...

  5. 图的深度优先搜索及拓扑排序

    本文将介绍图的深度优先搜索,并实现基于深度优先搜索的拓扑排序(拓扑排序适用于有向无环图,下面详细介绍). 1. 图的深度优先遍历要解决的问题 图的深度优先搜索与树的深度优先搜索类似,但是对图进行深度优 ...

  6. 图的深度优先搜索-递归

    图的深度优先搜索的过程: (1)从图的某个顶点V出发,访问V. (2)找出刚访问过的顶点的第一个未被访问的邻接点,访问该顶点.以该顶点为新顶点,重复此步骤,直到 刚顶点没有未bedi被访问的邻接点为止 ...

  7. 采用邻接矩阵形式存储图,进行图的深度优先搜索并输出结果。

    内容: 采用邻接矩阵形式存储图,进行图的深度优先搜索并输出结果. 步骤: 算法分析 本题需要利用邻接矩阵的形式存储图,并对图进行深度优先搜索并输出结果.大体上可以分为两个部分,一是采用邻接矩阵的方式存 ...

  8. 邻接矩阵实现图的深度优先搜索(1)

    邻接矩阵实现图的深度优先搜索(1) /************************************************************/ /****************** ...

  9. 数据结构与算法—图论之dfs、bfs(深度优先搜索、宽度优先搜索)

    文章目录 前言 邻接矩阵和邻接表 深度优先搜索(dfs) 宽度(广度)优先搜索(bfs) 总结与比较 前言 在有向图和无向图中,如果节点之间无权值或者权值相等,那么dfs和bfs时常出现在日常算法中. ...

最新文章

  1. 使用TensorFlow进行机器学习即服务
  2. Xamarin Android设置界面提示类型错误
  3. 列字段通用excel导入修改版
  4. Codeforces Round #661 (Div. 3)
  5. HOW-TO:带有MySQL的JEE应用程序中具有集群功能的Quartz Scheduler
  6. 软件或jar包等名字里的GA意思
  7. 彻底解决Spring MVC 中文乱码 问题
  8. 设计模式的C语言应用-导言-第一章
  9. Python——文件操作3——文件修改
  10. MySql Binlog初识
  11. Vue学习计划基础笔记(六) - 组件基础
  12. 手机计算机键盘技巧,【盲打计算器】看似简单,你不一定会的小技巧
  13. Xshell5 注册码 ,Xftp5 注册码,Xmanager5注册码
  14. 装修软件平台开发的优势
  15. excel生成随机数 / random number in excel
  16. https封装类,支持get/post请求
  17. cloudstack GuestNetwork Ingress-Egress rule
  18. Geany的所有主题文件
  19. 华硕笔记本刷BIOS
  20. MySQL笔记--2、3、4、5

热门文章

  1. 删除-ARMV8-V9-ATF-FFA学习笔记目录-2021-08
  2. [CISCN2018]crackme-java
  3. 2021-07-15
  4. python with contextmanager yield 语法糖
  5. 共享内存+Shellcode实现跨进程调用3环函数
  6. 【网络安全】如何使用QueenSono从ICMP提取数据
  7. 13.跨进程读写内存
  8. 根据表中的时间戳字段统计每天数据的数量
  9. 【ElementUI】 table表格尾部的合计行,固定表头却不显示合计行
  10. 【SSH】禁用root远程、修改ssh端口