? 本章承接上一章?具体的一些说明或者资料可以到上一章中寻找
1, 深度优先遍历
? ?说深度优先遍历之前 我们先说说走迷宫的走法,
?要探索迷宫中所有的通道,我们需要做以下几种事,
1):选择一条没有标记过的通道,在你走过的路上铺一条绳子;
2):标记所有你第一次路过的路口和通道;
3):当来到一个标记的路口(有绳子的路口)时回退到上一个路口
4):当回退到的路口已经没有可走的通道时继续回退。
这样绳子可以保证你总能找到一条出路,标记保证了你不会两次同时经历一条通道
?代码如下
class="java">package com.lxy.datastructure.graph;
public class DepthFirstSearch {
private boolean[] marked;//是否被访问过
private int count;//与s联通的顶点
public DepthFirstSearch(Graph g,int s) {
marked=new boolean[g.getV()];
dfs(g,s);
}
private void dfs(Graph g,int v){
marked[v]=true;
count++;
for(int w:g.adj(v)){
if(!marked(w))dfs(g, w);
}
}
public boolean marked(int w){
return marked[w];
}
public int count(){
return count;
}
}
?2,广度优先遍历
? ?1,取队列中的下一个顶点v并标记它
? ?2,将与v相邻的所有未被标记的顶点加入;
?重复以上步骤
?代码如下
package com.lxy.datastructure.graph;
import com.lxy.datastructure.queue.Queue;
import com.lxy.datastructure.stack.Stack;
public class BreadthFirstPaths {
private boolean[] marked;//访问标记
private int[] edgeTo;//
private int s;//起点
public BreadthFirstPaths(Graph g,int s){
this.s=s;
marked=new boolean[g.getV()];
edgeTo=new int[g.getV()];
bfs(g,s);
}
private void bfs(Graph g,int v){
Queue<Integer> queue=new Queue<Integer>();
marked[v]=true;
queue.push(v);
while(!queue.isEmpty()){
int h=queue.pop();
for(int w:g.adj(h)){
if(!marked(w)){
queue.push(w);
marked[w]=true;
edgeTo[w]=h;
}
}
}
}
public boolean marked(int v){
return marked[v];
}
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;
}
}
?
测试用例
package com.lxy.datastructure.graph;
import java.io.File;
import java.util.Arrays;
import java.util.Iterator;
import org.junit.Before;
import org.junit.Test;
import com.lxy.datastructure.queue.Queue;
import edu.princeton.cs.introcs.In;
import edu.princeton.cs.introcs.StdOut;
public class GraphTest {
String basePath=System.getProperty("user.dir");
File file1=null;
File file2=null;
Graph g1 =null;
@Before
public void setup(){
file1=new File(basePath,"data/graph/mediumG.txt");
file2=new File(basePath,"data/graph/tinyG.txt");
In in = new In(file2);
g1=new Graph(in);
}
@Test
public void testPrintGraph(){
System.out.println(g1.toString());
}
/**
* 深度优先遍历
*/
@Test
public void depthFirstPath(){
int s =0;
DeptFirstPaths path=new DeptFirstPaths(g1, s);
for (int v = 0; v < g1.getV(); v++) {
if (path.hasPathTo(v)) {
StdOut.printf("%d to %d: ", s, v);
for (int x : path.pathTo(v)) {
if (x == s) StdOut.print(x);
else StdOut.print("-" + x);
}
StdOut.println();
}
else {
StdOut.printf("%d to %d: not connected\n", s, v);
}
}
System.out.println(Arrays.toString(path.getEdgeTo()));
for(Iterator<Integer> it=path.pathTo(6).iterator();it.hasNext();){
System.out.println(it.next());
}
}
/**
* 广度优先遍历
*/
@Test
public void testBreadthFirstPath(){
int s =0;
BreadthFirstPaths path=new BreadthFirstPaths(g1, s);
for (int v = 0; v < g1.getV(); v++) {
if (path.hasPathTo(v)) {
StdOut.printf("%d to %d: ", s, v);
for (int x : path.pathTo(v)) {
if (x == s) StdOut.print(x);
else StdOut.print("-" + x);
}
StdOut.println();
}
else {
StdOut.printf("%d to %d: not connected\n", s, v);
}
}
}
}
?输出结果
广度优先遍历输出结果 0 to 0: 0 0 to 1: 0-1 0 to 2: 0-2 0 to 3: 0-5-3 0 to 4: 0-5-4 0 to 5: 0-5 0 to 6: 0-6 0 to 7: not connected 0 to 8: not connected 0 to 9: not connected 0 to 10: not connected 0 to 11: not connected 0 to 12: not connected 深度优先遍历输出结果 0 to 0: 0 0 to 1: 0-1 0 to 2: 0-2 0 to 3: 0-5-4-3 0 to 4: 0-5-4 0 to 5: 0-5 0 to 6: 0-5-4-6 0 to 7: not connected 0 to 8: not connected 0 to 9: not connected 0 to 10: not connected 0 to 11: not connected 0 to 12: not connected
?