深度优先搜索DFS
- 深度优先搜索,是从图中的一个顶点出发,每次遍历当前访问顶点的临界点,一直到访问的顶点没有未被访问过的临界点为止。然后采用依次回退的方式,查看来的路上每一个顶点是否有其它未被访问的临界点。访问完成后,判断图中的顶点是否已经全部遍历完成,如果没有,以未访问的顶点为起始点,重复上述过程。
- 深度优先搜索是一个不断回溯的过程,类似树的先序遍历。
- 可以采用递归或者栈来实现。
图的深度优先搜索
public class DFSTraverse{
//图的邻接矩阵
// 记录被访问顶点
private boolean[] verStatus;
// 顶点个数
private int vertexsNum = vertexs.length;
//深度优先搜索
public void DFSTra(){
verStatus = new boolean[vertexsNum];
for(int i = 0; i < vertexsNum; i++){
if(verStaus[i] == false){
DFS(i);
}
}
}
public void DFS(int i){
verStatus[i] = true;
for(int j = firstAdjVex(i); j >= 0; j = nextAdjVex(i, j)){
if(!verStaus[j]){
DFS(j);
}
}
}
// 返回与i相连的第一个顶点
private int firstAdjVex(int i) {
for (int j = 0; j < vertexsNum; j++) {
if (edges[i][j] == 1) {
return j;
}
}
return -1;
}
// 返回与i相连的下一个顶点
private int nextAdjvex(int i, int k) {
for (int j = k + 1; j < vertexsNum; j++) {
if (edges[i][j] == 1) {
return j;
}
}
return -1;
}
}
实际问题:
-
李白打酒
一天,李白提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少?请计算出所有可能方案的个数。public void dfs(int shop,int flower,int liquor){ if(shop == 0 && flower == 0 && liquor == 1){ //出口 answer++; } //枚举可能情况 //遇到店,店的数目-1,酒加倍 if(shop > 0) dfs(shop - 1, flower, liquor * 2); //遇到花,花的数目-1,酒-1 if(flower > 0) dfs(shop, flower-1, liquor - 1); }
广度优先搜索BFS
- 从图中的某一顶点出发,遍历每一个顶点时,依次遍历其所有的邻接点,然后再从这些邻接点出发,同样依次访问它们的邻接点。按照此过程,直到图中所有被访问过的顶点的邻接点都被访问到。
- 借助队列的先进先出(前一个节点出队,与他邻接的点全部进队)。
- 类似于树的层次遍历。
图的广度优先搜索
public class BFSTraverse {
private boolean[] verStatus;
// 顶点个数
private int vertexsNum = vertexs.length;
// 广搜
private void BFS() {
verStatus = new boolean[vertexsNum];
Queue<Integer> temp = new LinkedList<Integer>();
for (int i = 0; i < vertexsNum; i++) {
if (!verStatus[i]) {
verStatus[i] = true;
temp.offer(i);
while (!temp.isEmpty()) {
int j = temp.poll();
for (int k = firstAdjvex(j); k >= 0; k = nextAdjvex(j, k)) {
if (!verStatus[k]) {
verStatus[k] = true;
temp.offer(k);
}
}
}
}
}
}
// 返回与i相连的第一个顶点
private int firstAdjvex(int i) {
for (int j = 0; j < vertexsNum; j++) {
if (edges[i][j] > 0) {
return j;
}
}
return -1;
}
// 返回与i相连的下一个顶点
private int nextAdjvex(int i, int k) {
for (int j = (k + 1); j < vertexsNum; j++) {
if (edges[i][j] > 0) {
return j;
}
}
return -1;
}
}
【参考文档】
Java实现图的遍历(深搜与广搜)
深度优先搜索(DFS、深搜)和广度优先搜索(BFS、广搜)
DFS(深搜)算法