1、广度优先搜索(Breadth-first search)
BFS是最简单的图搜索算法之一,也是很多重要的图算法的原型。在Prim最小生成树算法和Dijkstra单源最短路径算法中,都采用了与BFS类似的思想。
BSF始终是将已发现和未发现顶点之间的边界,沿着其广度方向向外扩展。即算法首先会发现和s距离为k的所有顶点,然后才会发现和s距离为k+1的其他顶点。(层序遍历)
广度优先搜索构造了一棵广度优先树。
对于从可达的任意顶点v,广度优先搜索都能找到一条从s到v的最短路径(边数最少)。广度优先搜索所需要的时间O(V+E)。
实现:标记+队列
使用两种状态标记顶点
package mygraph;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import myutil.*;
public class MyBFS {
private boolean[] marked;
private int[] edgeTo;
private final int s; // source
public MyBFS(MyGraph G, int s) {
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
bfs(G, s);
}
private void bfs(MyGraph G, int s) {
MyQueue<Integer> queue = new MyQueue<Integer>();
marked[s] = true;
queue.enqueue(s);
while (!queue.isEmpty()) {
int v = queue.dequeue();
for (int w : G.adj(v)) {
if (!marked[w]) {
edgeTo[w] = v;
marked[w] = true;
queue.enqueue(w);
}
}
}
}
public boolean hasPathTo(int v) {
return marked[v];
}
public Iterable<Integer> pathTo(int v) {
if (!hasPathTo(v)) {
return null;
}
MyStack<Integer> path = new MyStack<Integer>();
for (int x = v; x != s; x = edgeTo[x]) {
path.push(x);
}
path.push(s);
return path;
}
public static void main(String[] args) {
MyGraph G = new MyGraph(new In("tinyG1.txt"), true);
int s = 0;
MyBFS bfs = new MyBFS(G, s);
for (int v = 0; v < G.V(); v++) {
StdOut.print(s + " to " + v + ": ");
if (bfs.hasPathTo(v)) {
for (int x : bfs.pathTo(v)) {
if (x == s)
StdOut.print(x);
else
StdOut.print("-" + x);
}
}
StdOut.println();
}
}
}
使用三种状态标记顶点
package mygraph;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.Point2D;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import myutil.*;
public class MyBFS3 {
private int edgeTo[];
private int color[];
private int distance[];
private final int WHITE = 0;
private final int GRAY = 1;
private final int BLAC