1.思考
这段时间有点忙,翻了一下,整个七月份才写了一篇文章:数据结构与算法系列二十七(图的基本概念与存储) 。关于图原计划是三部曲:基本概念、广度优先搜索代码实现、深度优先搜索代码实现。因为太忙就一直阁下了,这周不加班了,我们把该补上的补上。
那么关于图的一些基本概念,比如说:顶点、度、有向图、无向图等。我们就不多说了,如果你忘记了,可以再看一下上一篇文章。这一篇我们用程序员都喜欢的方式,开门见山,直接上图的广度优先搜索算法实现代码。那么,来吧。
#考考你:
1.你知道图的广度优先搜索算法的核心思想吗
2.你能用java语言实现图的广度优先搜索吗
2.案例
2.1.图的定义
/**
* 无向图-->邻接表存储
*/
class BfsGraph{
/**
* 顶点个数
*/
private int v;
/**
* 邻接表:每个顶点对应一个链表
*/
private LinkedList<Integer> adj[];
/**
* 构造方法,根据顶点个数定义图
* @param v
*/
public BfsGraph(int v){
this.v = v;
this.adj = new LinkedList[v];
// 初始化顶点链表
for(int i = 0; i < v; i++){
adj[i] = new LinkedList<Integer>();
}
}
/**
* 建立顶点之间的关系
* @param s
* @param t
*/
public void addEdge(int s, int t){
// 无向图
// 每一条边需要存储两次
adj[s].add(t);
adj[t].add(s);
}
}
2.2.广度优先搜索
/**
* 广度优先搜索
* 1.搜索从起始顶点 s,到终止顶点t的最短路径
* @param s 起始顶点
* @param t 终止顶点
*/
public void bfs(int s, int t){
// 起始定点,终止顶点是同一个顶点
if(s == t){
return;
}
// 记录已经访问过的顶点,避免顶点重复访问
boolean [] visited = new boolean[v];
visited[s] = true;
// 存储已经被访问过,但是相邻顶点还没有被访问的顶点
Queue<Integer> queue = new LinkedList<Integer>();
queue.add(s);
// 记录搜索路径,当从顶点s开始,搜索到顶点t后,prev数组存储的是搜索路径
// 注意:该搜索路径反向存储,即:prev[w]存储的是,顶点w是从哪一个前驱顶点遍历过来
// 比如:通过顶点2的邻接表访问到顶点3,那么prev[3]=2
int[] prev = new int[v];
for(int i = 0; i < v; i++){
prev[i] = -1;
}
// 开始广度优先搜索
while (queue.size() != 0){
// 出队
int w = queue.poll();
// 循环遍历访问顶点w的邻接表
for(int i = 0; i < adj[w].size(); i++){
// 取出元素,检查是否已经访问过
int q = adj[w].get(i);
// 未访问过
if(!visited[q]){
// 记录搜索路径
System.out.println("正在从顶点【" + w + "】访问顶点【" + q + "】");
prev[q] = w;
// 判断q顶点,是否是终止顶点t
if(q == t){
// 是目标终止顶点,广度优先搜索结束
System.out.println("顶点【" + s + "】到顶点【" + t + "】搜索结果:");
outSToTPath(prev, s, t);
return;
}
// q顶点不是目标终止顶点
// 将q顶点标记为已访问过,且相邻顶点未访问
visited[q] = true;
queue.add(q);
}// 未访问过if end
}// for end
}// while end
}
2.3.辅助打印输出
/**
* 递归打印输出搜索路径
* @param prev 搜索路径
* @param s 起始顶点
* @param t 终止顶点
*/
private void outSToTPath(int[] prev, int s, int t){
if(prev[t] != -1 && t != s){
outSToTPath(prev, s, prev[t]);
}
// 打印输出
System.out.print(t + "-->");
}
2.4.测试代码
/**
* 构建图,顶点:0 1 2 3 4 5 ,详情如下:
0 + + 1 + + 2
+ + +
+ + +
3 + + 4 + + 5
*/
public static void main(String[] args) {
// 1.创建6个顶点图
BfsGraph g = new BfsGraph(6);
// 2.建立顶点之间关系
// 2.1.顶点:0 1 ;0 3
g.addEdge(0,1);
g.addEdge(0,3);
// 2.2.顶点:1 2;1 4
g.addEdge(1,2);
g.addEdge(1,4);
// 2.3.顶点:2 5
g.addEdge(2,5);
// 2.4.顶点:3 4
g.addEdge(3,4);
// 2.5.顶点:4 5
g.addEdge(4,5);
// 3.开始广度优先搜索
// 3.1.搜索顶点:0 到5的最短路径
int s = 0;
int t = 5;
System.out.println("顶点【" + s + "】到顶点【" + t + "】搜索过程:");
g.bfs(s, t);
}
2.5.测试结果
D:\02teach\01soft\jdk8\bin\java com.anan.struct.graph.BFS
顶点【0】到顶点【5】搜索过程:
正在从顶点【0】访问顶点【1】
正在从顶点【0】访问顶点【3】
正在从顶点【1】访问顶点【2】
正在从顶点【1】访问顶点【4】
正在从顶点【2】访问顶点【5】
顶点【0】到顶点【5】搜索结果:
0-->1-->2-->5-->
Process finished with exit code 0