图的深度优先搜索(DFS)和广度优先搜索(BFS)算法
深度优先(DFS)
深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点。总结起来可以这样说:每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。
我们从这里可以看到,这样的访问策略是优先往纵向挖掘深入,而不是对一个结点的所有邻接结点进行横向访问。
算法大概过程:
1.把整个图的结构用矩阵来表示,如图:

2.我们从第一个顶点(v0)开始遍历,拿到第一个邻接点(二维矩阵里是v1),这个时候我们再对v1进行遍历,v0已经被访问过了所以选择跳过,这时再拿到v2,对v2开始进行遍历。。。以此类推!
代码实现如下:
// 获取某顶点的第一个邻接点
private int getFirstNeighbor(int index) {
for (int i = 0; i < vertexSize; i++) {
if (matrix[index][i] > 0 && matrix[index][i] < MAX_WEIGHT) {
// 找到了第一邻接点
return i;
}
}
return -1;
} // 根据前一个邻接点下标,来取得下一个邻接点
/**
* @param v1
* 表示要找的顶点
* @param index
* 表示该顶点相对于哪个邻接点去获取下一个邻接点
* @return
*/
private int getNextNeighbor(int v1, int index) {
for (int i = index + 1; i < vertexSize; i++) {
if (matrix[v1][i] > 0 && matrix[v1][i] < MAX_WEIGHT) {
return i;
}
}
return -1;
} private void depthSearch(int i) {
isVisited[i] = true;// 证明当前顶点被访问过了
// 获取当前顶点的邻接点
int w = getFirstNeighbor(i);
// 只要w不是-1
while (w != -1) {
// 证明i确实有邻接点
// 判断w是否被访问过
if (!isVisited[w]) {
// 如果没有被访问过,就继续深度遍历w顶点
System.out.println("深度优先访问到的顶点:" + w);
depthSearch(w);
}
// 如果当前邻接点被访问过了,就继续搜索除了这个w外其他的点
w = getNextNeighbor(i, w);
}
} public void depthFirstSearch() {
// 这是对外提供
isVisited = new boolean[vertexSize];
for (int i = 0; i < vertexSize; i++) {
if (!isVisited[i]) {
System.out.println("深度优先访问到的顶点:" + i);
depthSearch(i);
}
}
// 遍历完后,记得把布尔数组归为
isVisited = new boolean[vertexSize];
}
广度优先(BFS)
广度优先搜索类似于我们的二叉树的层次遍历,我们还是以v0作为起始点,根据二维矩阵,我们找到v0的第一个邻接点,之后再找到v0的第二个邻接点,直到找不到v0的邻接点为止,由图可知,v0就俩邻接点v1,v5。遍历完后,继续遍历v1的邻接点,v1的遍历完后,开始遍历v5的。。。以此类推!
代码如下:
// 广度优先遍历算法
public void broadFirstSearch() {
isVisited = new boolean[vertexSize];
for (int i = 0; i < vertexSize; i++) {
if (!isVisited[i]) {
System.out.println("广度优先访问到的顶点:" + i);
broadSearch(i);
}
}
isVisited = new boolean[vertexSize];
} private void broadSearch(int i) {
// 类似于二叉树的层次遍历
int u, w;
LinkedList<Integer> queue = new LinkedList<>();
isVisited[i] = true;
queue.add(i);
while (!queue.isEmpty()) {
u = queue.removeFirst();// 顶点
w = getFirstNeighbor(u);
while (w != -1) {
if (!isVisited[w]) {
System.out.println("广度优先访问到的顶点:" + w);
isVisited[w] = true;
queue.add(w);
}
// 拿到后面的邻接点
w = getNextNeighbor(u, w);
}
}
}
图的深度优先搜索(DFS)和广度优先搜索(BFS)算法的更多相关文章
- 图的深度优先遍历(DFS)和广度优先遍历(BFS)
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 图的深度优先遍历(DFS)和广度优先遍历(BFS)算法分析
1. 深度优先遍历 深度优先遍历(Depth First Search)的主要思想是: 1.首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点: 2.当没有未访问过的顶点时,则回 ...
- 【C++】基于邻接矩阵的图的深度优先遍历(DFS)和广度优先遍历(BFS)
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析
转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...
- 深度优先搜索DFS和广度优先搜索BFS
DFS简介 深度优先搜索,一般会设置一个数组visited记录每个顶点的访问状态,初始状态图中所有顶点均未被访问,从某个未被访问过的顶点开始按照某个原则一直往深处访问,访问的过程中随时更新数组visi ...
- 图的 储存 深度优先(DFS)广度优先(BFS)遍历
图遍历的概念: 从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(Traversing Graph).图的遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础.图的 ...
- js图的数据结构处理----邻链表,广度优先搜索,最小路径,深度优先搜索,探索时间拓扑
//邻居连表 //先加入各顶点,然后加入边 //队列 var Queue = (function(){ var item = new WeakMap(); class Queue{ construct ...
- 图的深度优先搜索算法DFS
1.问题描写叙述与理解 深度优先搜索(Depth First Search.DFS)所遵循的策略.如同其名称所云.是在图中尽可能"更深"地进行搜索. 在深度优先搜索中,对最新发现的 ...
随机推荐
- numpy-添加操作大全
合并 hstack(tup):按行合并 [前面有个 h,可以理解为 行,这样方便记忆] vstack(tup):按列合并 参数虽然是 tuple,但是 list 也行,可以合并2个或者多个数组. a= ...
- Codeforces 1220D. Alex and Julian
传送门 首先考虑怎样的集合一定是合法的 发现全部是奇数的集合一定合法,因为每次都是奇数连偶数,偶数连奇数 然后考虑如果集合同时有奇数和偶数是否一定不合法,结论是一定不合法,证明如下: 设某个奇数为 $ ...
- NEO4J亿级数据导入导出以及数据更新
1.添加配置 apoc.export.file.enabled=true apoc.import.file.enabled=true dbms.directories.import=import db ...
- Elasticsearch入门教程(一):Elasticsearch及插件安装
原文:Elasticsearch入门教程(一):Elasticsearch及插件安装 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...
- ES使用text类型字段排序报错
elasticsearch text字段排序报错解决使用elasticsearch 进行排序的时候,我们一般都会排序数字.日期.但是在排序text类型的时候就会出现错误. GET xytest/sut ...
- lamp项目上线流程简述 (ubuntu16.04 )
1 新建一个sudo用户,而不是直接用root操作 ① 新建用户可参考 https://www.cnblogs.com/bushuwei/p/10880182.html ② 赋予sudo权限: ...
- js对时间戳的处理 获取时间,昨天,今天,明天,时间不同格式
1.获取昨天,今天,明天的时间 //昨天的时间 var day1 = new Date(); day1.setTime(day1.getTime()-24*60*60*1000); var s1 = ...
- 剑指offer-1:旋转数组的最小数字
旋转数组的最小数字1.题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2 ...
- js 继承,Object.setPrototypeOf | Object.getPrototypeOf | Object.create class
https://juejin.im/post/5cfd9d30f265da1b94213d28#heading-14 https://juejin.im/post/5d124a12f265da1b91 ...
- XXE漏洞攻击与防御
转自https://www.jianshu.com/p/7325b2ef8fc9 0x01 XML基础 在聊XXE之前,先说说相关的XML知识吧. 定义 XML用于标记电子文件使其具有结构性的标记语言 ...