本文转载自:https://www.jianshu.com/p/70952b51f0c8
深度优先搜索属于图算法的一种,英文缩写为DFS即DepthFirst Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
结合有向图
深度优先搜索在搜索过程中访问某个顶点后,需要递归地访问此顶点的所有未访问过的相邻顶点。
初始条件下所有节点为白色,选择一个作为起始顶点,按照如下步骤遍历:
a.选择起始顶点涂成灰色,表示还未访问
b.从该顶点的邻接顶点中选择一个,继续这个过程(即再寻找邻接结点的邻接结点),一直深入下去,直到一个顶点没有邻接结点了,涂黑它,表示访问过了
c.回溯到这个涂黑顶点的上一层顶点,再找这个上一层顶点的其余邻接结点,继续如上操作,如果所有邻接结点往下都访问过了,就把自己涂黑,再回溯到更上一层。
d.上一层继续做如上操作,知道所有顶点都访问过。
用图可以更清楚的表达这个过程:
// too lazy to place picture
图可以通过如下邻接矩阵表示:
int maze[5][5] = {
{ 0, 1, 1, 0, 0 },
{ 0, 0, 1, 0, 1 },
{ 0, 0, 1, 0, 0 },
{ 1, 1, 0, 0, 1 },
{ 0, 0, 1, 0, 0 }
};
从顶点1开始做深度搜索:
初始状态,从顶点1开始
依次访问过顶点1,2,3后,终止于顶点3
从顶点3回溯到顶点2,继续访问顶点5,并且终止于顶点5
从顶点5回溯到顶点2,并且终止于顶点2
从顶点2回溯到顶点1,并终止于顶点1
从顶点4开始访问,并终止于顶点4
上面的图可以通过如下邻接矩阵表示:
DFS递归实现
import java.util.LinkedList;
import java.util.Queue;
/**
* Created by viruser on 2018/4/4.
*/
public class Maze {
int[][] maze;
int[] visited;
int count;
Queue<Integer> queue = new LinkedList<Integer>();
public Maze(int[][] maze, int[] visited, int count) {
this.maze = maze;
this.visited = visited;
this.count = count;
}
public void Dfs(int start) {
visited[start] = 1;
queue.offer(start);
for (int i = 1; i < count+1; i++) {
// 第 i 个数没有被访问,并且第 start 个数有路径可以访问到第 i 个数
if (visited[i] != 1 && maze[start-1][i-1] ==1) {
Dfs(i);
}
}
}
public void test() {
for (int i = 1; i < count+1; i++) {
if (visited[i] == 1) {
continue;
}
Dfs(i);
}
}
public static void main(String[] args) {
int maze[][] = {
{ 0, 1, 1, 0, 0 },
{ 0, 0, 1, 0, 1 },
{ 0, 0, 1, 0, 0 },
{ 1, 1, 0, 0, 1 },
{ 0, 0, 1, 0, 0 }
};
int visited[] = new int[6];
visited[0] = 0;
Maze m = new Maze(maze, visited, 5);
m.test();
Queue<Integer> s = m.queue;
int k = s.size();
for (int i = 0; i < k; i++) {
System.out.println(s.poll());
}
}
}
DFS非递归实现,借助一个栈
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* Created by viruser on 2018/4/4.
*/
public class Mazea {
int[][] maze;
int[] visited;
int count;
Queue<Integer> queue = new LinkedList<Integer>();
Stack<Integer> stack = new Stack<Integer>();
public Mazea(int[][] maze, int[] visited, int count) {
this.maze = maze;
this.visited = visited;
this.count = count;
}
public void Dfs(int start) {
visited[start] = 1;
stack.push(start);
boolean is_push = false;
while (!stack.isEmpty()) {
is_push = false;
int v = stack.peek();
for (int i = 1; i <= count ; i++) {
if (visited[i] != 1 && maze[v-1][i-1] == 1) {
visited[i] = 1;
stack.push(i);
is_push = true;
break;
}
}
if (!is_push) {
System.out.println(v);
stack.pop();
}
}
}
public void test() {
for (int i = 1; i < count+1; i++) {
if (visited[i] == 1) {
continue;
}
Dfs(i);
}
}
public static void main(String[] args) {
int maze[][] = {
{ 0, 1, 1, 0, 0 },
{ 0, 0, 1, 0, 1 },
{ 0, 0, 1, 0, 0 },
{ 1, 1, 0, 0, 1 },
{ 0, 0, 1, 0, 0 }
};
int visited[] = new int[6];
visited[0] = 0;
Mazea m = new Mazea(maze, visited, 5);
m.test();
Queue<Integer> s = m.queue;
int k = s.size();
for (int i = 0; i < k; i++) {
System.out.println(s.poll());
}
}
}