1. 广度优先搜索(BFS)
广度优先搜索(Breadth-First-Search),简称为 BFS。直观地讲,它其实就 是一种“地毯式”层层推进的搜索策略,即先查找离起始顶点最近的,然后是次近的,依次 往外搜索。
过程图如下:
BFS代码如下:
class Graph {
public int v; //顶点个数
public LinkedList<Integer>[] adj;//邻接表
public LinkedList<Integer>[] getAdj() {
return adj;
}
public int getV() {
return v;
}
public Graph(int v){
this.v = v;
adj = new LinkedList[v];
for(int i=0;i<v;i++){
adj[i] = new LinkedList<Integer>();
}
}
public void addEdge(int s,int t){
adj[s].add(t);
adj[t].add(s);
}
}
public class GraphTest1 {
//构造图
public Graph constructGraph(){
Graph graph = new Graph(8);
graph.addEdge(0,1);
graph.addEdge(0,3);
graph.addEdge(1,0);
graph.addEdge(1,2);
graph.addEdge(1,4);
graph.addEdge(2,1);
graph.addEdge(2,5);
graph.addEdge(3,0);
graph.addEdge(3,4);
graph.addEdge(4,1);
graph.addEdge(4,3);
graph.addEdge(4,5);
graph.addEdge(4,6);
graph.addEdge(5,2);
graph.addEdge(5,4);
graph.addEdge(5,7);
graph.addEdge(6,4);
graph.addEdge(6,7);
graph.addEdge(7,5);
graph.addEdge(7,6);
return graph;
}
@Test
public void test1(){
BFS(0,7);
System.out.println();
BFS1(0,7);
}
//广度优先算法
public void BFS(int s,int t){
Graph graph = constructGraph();
int v = graph.getV();
boolean[] visited = new boolean[v];
int[] prev = new int[v];
Queue<Integer> queue = new LinkedList<>();
queue.add(s);
visited[s] = true;
for(int i=0;i<v;i++){
prev[i] = -1;
}
while (!queue.isEmpty()){
int q = queue.poll();
for(int a:graph.adj[q]){
System.out.println(q+" "+a);
if(!visited[a]){
visited[a] = true;
prev[a] = q;
if(a==t){
print(prev,s,t);
return;
}
queue.add(a);
}
}
}
}
void print(int[] prev, int s, int t) { // 递归打印 s->t 的路径
if(prev[t] != -1 && t != s){
print(prev,s,prev[t]);
}
System.out.print(t+" ");
}
}
2. 深度优先搜索(DFS)
深度优先搜索(Depth-First-Search),简称 DFS。
最直观的例子就是“走迷宫”。 假设你站在迷宫的某个岔路口,然后想找到出口。你随意选择一个岔路口来走,走着走着发
现走不通的时候,你就回退到上一个岔路口,重新选择一条路继续走,直到最终找到出口。 这种走法就是一种深度优先搜索策略。
具体DFS的过程如图:
DFS代码如下:
class Graph {
public int v; //顶点个数
public LinkedList<Integer>[] adj;//邻接表
public LinkedList<Integer>[] getAdj() {
return adj;
}
public int getV() {
return v;
}
public Graph(int v){
this.v = v;
adj = new LinkedList[v];
for(int i=0;i<v;i++){
adj[i] = new LinkedList<Integer>();
}
}
public void addEdge(int s,int t){
adj[s].add(t);
adj[t].add(s);
}
}
public class GraphTest1 {
public Graph constructGraph(){
Graph graph = new Graph(8);
graph.addEdge(0,1);
graph.addEdge(0,3);
graph.addEdge(1,0);
graph.addEdge(1,2);
graph.addEdge(1,4);
graph.addEdge(2,1);
graph.addEdge(2,5);
graph.addEdge(3,0);
graph.addEdge(3,4);
graph.addEdge(4,1);
graph.addEdge(4,3);
graph.addEdge(4,5);
graph.addEdge(4,6);
graph.addEdge(5,2);
graph.addEdge(5,4);
graph.addEdge(5,7);
graph.addEdge(6,4);
graph.addEdge(6,7);
graph.addEdge(7,5);
graph.addEdge(7,6);
return graph;
}
@Test
public void DFSTest(){
Graph graph = constructGraph();
int v = graph.getV();
boolean[] visited = new boolean[v];
int[] prev = new int[v];
for(int i=0;i<v;i++){
prev[i] = -1;
}
DFS(visited,prev,graph,0,6);
print(prev,0,6);
}
//深度遍历算法
public void DFS(boolean[] visited,int[] prev,Graph graph,int s,int t){
visited[s] = true;
if(s == t) {
return;
}
for(int dd:graph.getAdj()[s]){
if(!visited[dd]){
visited[dd] = true;
prev[dd] = s;
DFS(visited,prev,graph,dd,t);
}
}
}
void print(int[] prev, int s, int t) { // 递归打印 s->t 的路径
if(prev[t] != -1 && t != s){
print(prev,s,prev[t]);
}
System.out.print(t+" ");
}
}