在上一篇文章我们用java演示了图的数据结构以及图涉及到的深度优先遍历算法,本篇文章将继续演示图的广度优先遍历算法。广度优先遍历算法主要是采用了分层的思想进行数据搜索。其中也需要使用另外一种数据结构队列,本篇文章为了使代码更加优雅,所有使用java中Linkedlist集合来进行模拟队列。因为该集合有在队列尾部添加元素和从队头取出元素的API。

算法思想:

1.先访问一个元素,然后放到队列中,并且标记已经访问过该元素。

2.然后判断队列是否为空,不为空则取出队头元素。

3.然后取出队头元素的第一个邻接节点并判断该元素是否存在。

4.如果存在再次判断该元素有没有被访问过。

5.如果没有访问过则标记为访问过。同时放到队列中。

6.如果访问过则以头节点为前驱节点,第一个邻接节点为第二个参数查找队头节点的下面的邻接节点

代码以下图为参考:

代码如下:

  1 import java.util.ArrayList;
2 import java.util.Arrays;
3 import java.util.LinkedList;
4
5
6 public class Graph {
7
8 //创建一个集合用来存放顶点
9 private ArrayList<String> arrayList;
10 //创建一个二位数组来作为邻接矩阵
11 private int[][] TwoArray;
12 //边的数目
13 private int numOfEdges;
14 //使用一个数组记录节点是否被访问过
15 private boolean[] isVisted;
16 public static void main(String[] args) {
17 Graph graph = new Graph(5);
18 //测试
19 String[] ver={"A","B","C","D","E"};
20 //将节点放到集合中
21 for (String s : ver) {
22 graph.InsertVex(s);
23 }
24 //设置边
25 //A-B A-C B-C B-D B-E
26 graph.InsertEdeges(0,1,1);
27 graph.InsertEdeges(0,2,1);
28 graph.InsertEdeges(1,2,1);
29 graph.InsertEdeges(1,3,1);
30 graph.InsertEdeges(1,4,1);
31 //显示
32 graph.Show();
33 graph.BFS();
34 }
35
36 //初始化数据
37 public Graph(int n){
38 arrayList=new ArrayList<>(n);
39 TwoArray=new int[n][n];
40 numOfEdges=0;
41 isVisted=new boolean[n];
42 }
43
44 /**
45 * 根据节点的下标返回第一个邻接节点的下标
46 * @param index 节点的下标
47 * @return
48 */
49 public int getFirstVex(int index){
50 for (int i = 0; i < arrayList.size(); i++) {
51 if(TwoArray[index][i]!=0){
52 return i;
53 }
54 }
55 return -1;
56 }
57
58 /**
59 * 根据前一个节点下标获取下一个节点的下标
60 * @param v1 找到的第一个节点的
61 * @param v2 找到的第一个邻接节点并且被访问过的
62 * @return
63 */
64 public int getNextVex(int v1,int v2){
65 for (int i = v2+1; i < numEdges(); i++) {
66 if(TwoArray[v1][i]!=0){
67 return i;
68 }
69 }
70 return -1;
71 }
72
73 /**
74 * 广度优先遍历
75 * @param isVisted 记录是否被访问过的数组
76 * @param i 想要访问的节点下标
77 */
78 public void BFS(boolean[] isVisted,int i){
79 //表示队列头节点的下标
80 int u;
81 //用于存放队列头节点的第一个邻接节点
82 int w;
83 //定义一个队列用来存放节点
84 LinkedList<Object> queue = new LinkedList<>();
85 //访问该节点
86 System.out.print(getValue(i)+"->");
87 //在数组中标记为该下标已经被访问过了
88 isVisted[i]=true;
89 //把访问过的节点下标放到队列中,放到队列的尾部
90 queue.addLast(i);
91 //判断队列是否为空
92 while (!queue.isEmpty()){
93 //队列不为空,那么取出队列的头节点的下标
94 u=(Integer) queue.removeFirst();
95 //获取头节点的第一个邻接节点的下标
96 w = getFirstVex(u);
97 //判断该节点是否存在
98 while (w!=-1){
99 //说明存在,在判断是否被访问过
100 if(!isVisted[w]){
101 //没有访问过,标记为已访问
102 isVisted[w]=true;
103 //输出
104 System.out.print(getValue(w)+"->");
105 //访问完加入队列中
106 queue.addLast(w);
107 }
108 //以u作为前驱节点,w作为u刚刚访问过的节点,来查找w的下一个邻接节点
109 w = getNextVex(u, w);
110 }
111 }
112 }
113
114 public void BFS(){
115 for (int i = 0; i < arrayList.size(); i++) {
116 if(!isVisted[i]){
117 BFS(isVisted,i);
118 }
119 }
120 }
121
122 /**
123 * 添加节点
124 * @param vex
125 */
126 public void InsertVex(String vex){
127 arrayList.add(vex);
128 }
129
130 /**
131 * 设置边
132 * @param v1 第一个节点对应的下标
133 * @param v2 第二节点对应的下标
134 * @param weight 两个节点对应的权值
135 */
136 public void InsertEdeges(int v1,int v2,int weight){
137 TwoArray[v1][v2]=weight;
138 TwoArray[v2][v1]=weight;
139 numOfEdges++;
140 }
141
142 /**
143 * 返回节点对应的个数
144 * @return
145 */
146 public int numVex(){
147 return arrayList.size();
148 }
149
150 /**
151 * 返回边的总个数
152 * @return
153 */
154 public int numEdges(){
155 return numOfEdges;
156 }
157
158 /**
159 * 显示邻接矩阵(图的展示)
160 */
161 public void Show(){
162 for (int[] ints : TwoArray) {
163 System.out.println(Arrays.toString(ints));
164 }
165 }
166
167 /**
168 * 根据下标获取对应的数据
169 * @param i 下标
170 * @return
171 */
172 public String getValue(int i){
173 return arrayList.get(i);
174 }
175
176 public int getWeight(int v1,int v2){
177 int weight=TwoArray[v1][v2];
178 return weight;
179 }
180 }

图的广度优先遍历算法(BFS)的更多相关文章

  1. 《图论》——广度优先遍历算法(BFS)

    十大算法之广度优先遍历: 本文以实例形式讲述了基于Java的图的广度优先遍历算法实现方法,详细方法例如以下: 用邻接矩阵存储图方法: 1.确定图的顶点个数和边的个数 2.输入顶点信息存储在一维数组ve ...

  2. 数据结构与算法之PHP用邻接表、邻接矩阵实现图的广度优先遍历(BFS)

    一.基本思想 1)从图中的某个顶点V出发访问并记录: 2)依次访问V的所有邻接顶点: 3)分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,直到图中所有已被访问过的顶点的邻接点都被访问到. 4) ...

  3. 图的广度优先遍历(bfs)

    广度优先遍历: 1.将起点s 放入队列Q(访问) 2.只要Q不为空,就循环执行下列处理 (1)从Q取出顶点u 进行访问(访问结束) (2)将与u 相邻的未访问顶点v 放入Q, 同时将d[v]更新为d[ ...

  4. 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)

    参考网址:图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) - 51CTO.COM 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath ...

  5. PTA 邻接表存储图的广度优先遍历(20 分)

    6-2 邻接表存储图的广度优先遍历(20 分) 试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(V ...

  6. 饥饿的小易(枚举+广度优先遍历(BFS))

    题目描述 小易总是感觉饥饿,所以作为章鱼的小易经常出去寻找贝壳吃.最开始小易在一个初始位置x_0.对于小易所处的当前位置x,他只能通过神秘的力量移动到 4 * x + 3或者8 * x + 7.因为使 ...

  7. PTA 邻接表存储图的广度优先遍历

    试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ) 其中LGraph是邻接表存储的 ...

  8. 算法学习 - 图的广度优先遍历(BFS) (C++)

    广度优先遍历 广度优先遍历是非经常见和普遍的一种图的遍历方法了,除了BFS还有DFS也就是深度优先遍历方法.我在我下一篇博客里面会写. 遍历过程 相信每一个看这篇博客的人,都能看懂邻接链表存储图. 不 ...

  9. 怎样实现广度优先遍历(BFS)

    BFS过程: 一:訪问顶点V,并标记V为已经訪问 二:顶点V入队列 三:假设队列非空.进行运行,否则算法结束 四:出队列取得对头顶点u,假设顶点未被訪问,就訪问该顶点,并标记该顶点为已经訪问 五:查找 ...

随机推荐

  1. vue中携带token以及发送ajax

    在项目中基本登录都会存在token,而我们也就需要在每次发送ajax的时候就必须携带他.从而最有效的办法,就是在设置请求头携带token,这样设置一次后面的每一次都会携带着这个token. 一:设置请 ...

  2. 使用postman添加cookie失败和cookie消失问题

    例如 groupId=2; path=/; domain=.www.baidu.com; HttpOnly; Expires=Tue, 16 Jul 2019 03:42:12 GMT; 添加失败和c ...

  3. ElasticSearch--一、使用场景以及对应软件配置安装

    废话不多说,直接来硬的!我在使用的时候使用的是mysql数据库. 一.ElasticSearch概念和使用场景 1.当我们需要搜索海量数据的时候,就可能会用到.以下使用的场景有哪些呢? 搜索海量数据 ...

  4. Java基础--接口回调(接口 对象名 = new 类名)理解

    接口 对象名1 = new 类名和类名 对象名2 = new 类名的区别是什么? 实例 /** *Person.java 接口 */ public interface Person { void in ...

  5. java对象

    原文链接http://zhhll.icu/2020/04/26/java%E5%9F%BA%E7%A1%80/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/java%E5% ...

  6. 攻防世界_MISC进阶区_Get-the-key.txt(详细)

    攻防世界MISC进阶之Get-the-key.txt 啥话也不说,咱们直接看题吧! 首先下载附件看到一个压缩包: 我们直接解压,看到一个文件,也没有后缀名,先用 file 看一下文件属性: 发现是是L ...

  7. JDK1.7-HashMap原理

    JDK1.7 HashMap 如何在源码上添加自己的注释 打开jdk下载位置 解压src文件夹,打开idea,ctrl+shift+alt+s打开项目配置 选择jdk版本1.7,然后点击Sourcep ...

  8. RandomForest 随机森林算法与模型参数的调优

    公号:码农充电站pro 主页:https://codeshellme.github.io 本篇文章来介绍随机森林(RandomForest)算法. 1,集成算法之 bagging 算法 在前边的文章& ...

  9. library cache pin解决方法

    library cache pin大部分都是因为编译存储过程造成的 查找造成问题的数据库对象(一般为存储过程) SELECT * FROM v$session_wait WHERE event = ' ...

  10. MySQL全面瓦解18:自定义函数

    定义 我们之前学习了MySQL的内置函数,非常丰富,满足了我们对数据操作的大部分需求. 但是如果有一些复杂的业务逻辑在数据库层面就可以完成,无需在程序层面完成的时候,这时候就可以写成MySQL自定义函 ...