单点路径问题在图的处理领域中十分重要,从输入流中读取一个图从从命令行得到一个起点,然后打印从起点到与它连通的每个顶点之间的一条路径。
深度优先找路径
下面扩展了尝试优先搜索代码,添加一一个实例变量edgeTo[]整型数组来起到Tremaux搜索中绳子的作用,这个数组可以找到从每个与s连通的顶点回到s的路径。它会记住每个顶点到起点的路径,而不是记录当前顶点到起点的路径
代码
package algorithm.graph.gopath;
import algorithm.graph.Graph;
import java.util.Stack;
/**
* 描述:深度优先找打通的路径
* Created by zjw on 2021/7/25 13:13
*/
public class DepthFirstPaths {
private boolean[] marked; //这个顶点上调用过dfs()了吗?
private int[] edgeTo;
private final int s;
public DepthFirstPaths(Graph G, int s) {
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
dfs(G, s);
}
private void dfs(Graph G, int v) {
marked[v] = true;
for (Integer w : G.adj(v)) {
if (!marked[w]) {
edgeTo[w] = v;
dfs(G, w);
}
}
}
public boolean hasPathTo(int v) {
return marked[v];
}
public Iterable<Integer> pathTo(int v) {
if (!hasPathTo(v)) return null;
Stack<Integer> path = new Stack<Integer>();
for (int x = v; x !=s ; x=edgeTo[x]) path.push(x);
path.push(s);
return path;
}
}
广度优先找路径
使用队列来保存所有已经被标记过但其邻接表还未被检查过的顶点,先将起点加入队列,然后重复以下步骤直到队列为空;
- 取队列中的下一个顶点v并标记它
- 将与v相邻的所有未被标记过的顶点加入队列
代码
package algorithm.graph.gopath;
import algorithm.graph.Graph;
import java.util.Stack;
/**
* 描述:广度优先
* Created by zjw on 2021/7/25 13:26
*/
public class BreadthFirstPaths {
private boolean[] marked; //到达该顶点的最短路径已知吗
private int[] edgeTo; //到达该顶点的已知路径上的最后一个顶点
private final int s; //起点
public BreadthFirstPaths(Graph G, int s) {
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
bfs(G, s);
}
public void bfs(Graph G, int s) {
Queue<Integer> queue = new Queue<Integer>();
marked[s] = true; //标记起点
queue.enqueue(s);
while (!queue.isEmpty()) {
int v = queue.dequeue();//从队列中删去下一顶点
for (Integer 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;
Stack<Integer> path = new Stack<Integer>();
for (int x = v; x !=s ; x=edgeTo[x]) path.push(x);
path.push(s);
return path;
}
class Queue<Item> {
private class Node{
private Item item;
private Queue.Node next;
}
private Queue.Node first;
private Queue.Node last;
int N = 0;
private boolean isEmpty() {
return N == 0;
}
public int size() {
return N;
}
//�����
public void enqueue(Item item) {
Queue.Node node = new Queue.Node();
node.item = item;
node.next = null;
if (isEmpty()) {
last = node;
first = node;
} else {
last.next = node;
last = node;
}
N++;
}
//������
public Item dequeue() {
Node node = first;
first = first.next;
N--;
return node.item;
}
}
}