深度优先遍历(DSF):
思想:可以使用递归和非递归来完成dsf
简述一下非递归方法的思想:是使用队列还是栈呢?首先要明确队列和栈各自的特点,队列是先进先出,栈是后进先出出,想一想深度优先检索,重点是在深度,要想深度向下,就需要沿着一条线从一个节点一直向下
遍历直到没有节点可遍历位置。那么问题来了,要想沿着一条线不断向下,就需要不断的找起始节点的下一个节点
再下一个节点,再再下一个节点......直到最后,可以通过一个节点的邻接节点来找到其“下一个节点”,
所以使用栈,从第一个节点开始,不断的入栈弹栈,利用栈的后进先出的特点来找出节点的某一邻接节点作为
遍历路径上的下一个节点
接下来上张图来说明深度遍历
再看B的邻接节点有C,I,G选择C作为B的下一个节点,此时B也已经遍历过了,一次类推比如遍历的顺序为A,B,C,D,E,F,G,H,
没有能往下继续遍历的节点,所以开始回溯,看是否还有节点没有遍历完,首先回溯到节点G,发现G的邻接节点已经
完全遍历完了,在回溯到F,同样如此,然后F,E,D,C依次回溯,到C发现C的邻接节点I没有遍历,所以把I作为下一个节点开始遍历
,遍历完再回溯,直达回溯到A节点为止。所以应为再回溯的过程中要找上一个节点,所以用栈非常适合深度优先遍历
深度优先遍历既可以使用递归方法又可以使用非递归方法
下面呈上一段详细代码
package SevenProvience.tital2;
import java.util.Stack;
public class DFS {
//存储节点信息
private char[] vertices;
//存储边信息(邻接矩阵)
private int[][] arcs;
//图的节点数
private int vexnum;
//记录节点是否已被遍历
private boolean[] visited;
//初始化
public DFS(int n){
vexnum=n;
vertices=new char[n];
arcs=new int[n][n];
visited=new boolean[n];
//将矩阵所有的边都初始化为0
for(int i=0;i<vexnum;i++){
for(int j=0;j<vexnum;j++){
arcs[i][j]=0;
}
}
}
//添加边(无向图)
public void addEdge(int i,int j){
//边的头尾不能为同一个节点
if(i==j)return;
arcs[i][j]=1;
arcs[j][i]=1;
}
//设置节点集
public void setVertices(char[] vertices){
this.vertices=vertices;
}
//设置节点访问标记
public void setVisited(boolean[] visited){
this.visited=visited;
}
//打印遍历节点
public void visit(int i){
System.out.print(vertices[i]+" ");
}
//非递归方法是实现深度优先遍历
public void DFSTraverse(){
//初始化节点遍历标记
for(int i=0;i<vexnum;i++){
visited[i]=false;
}
//创建一个栈
Stack<Integer> s=new Stack<Integer>();
//对非联通图执行循环进行遍历以至于所有节点都遍历到
//若是连通图该for循环只执行一次
for(int i=0;i<vexnum;i++){
if(!visited[i]){
//连通子图起始节点
s.add(i);
do{
//出栈
int curr=s.pop();
//如果节点还没有被遍历到,则遍历该节点并将该节点入栈用来遍历其子节点
if(visited[curr]==false){
//遍历并打印
visit(curr);
visited[curr]=true;
//没遍历的子节点入栈
for(int j=vexnum-1;j>=0;j--){
if(arcs[curr][j]==1&&visited[j]==false){
s.add(j);
}
}
}
}while(!s.isEmpty());
}
}
}
//从第i个节点开始深度优先遍历
private void traverse(int i){
//标记第i个节点已被遍历
visited[i]=true;
//打印当前遍历的节点
visit(i);
//遍历邻接矩阵中第i个节点的直接连通关系
for(int j=0;j<vexnum;j++){
//目标节点与当前节点直接连通并没有被访问,递归遍历
if(arcs[i][j]==1&&visited[j]==false){
traverse(j);
}
}
}
//图的深度优先遍历(递归法)
public void DFSTraverse1(){
//初始化节点遍历标记
for(int i=0;i<vexnum;i++){
visited[i]=false;
}
//从没有被遍历的节点开始深度遍历
//连通图的话这个循环只会执行一次
for(int i=0;i<vexnum;i++){
if(visited[i]==false)
traverse(i);
}
}
}
package SevenProvience.tital2;
public class test {
public static void main(String[] args) {
DFS g = new DFS(9);
char[] vertices = {'A','B','C','D','E','F','G','H','I'};
g.setVertices(vertices);
g.addEdge(0, 1);
g.addEdge(0, 5);
g.addEdge(1, 0);
g.addEdge(1, 2);
g.addEdge(1, 6);
g.addEdge(1, 8);
g.addEdge(2, 1);
g.addEdge(2, 3);
g.addEdge(2, 8);
g.addEdge(3, 2);
g.addEdge(3, 4);
g.addEdge(3, 6);
g.addEdge(3, 7);
g.addEdge(3, 8);
g.addEdge(4, 3);
g.addEdge(4, 5);
g.addEdge(4, 7);
g.addEdge(5, 0);
g.addEdge(5, 4);
g.addEdge(5, 6);
g.addEdge(6, 1);
g.addEdge(6, 3);
g.addEdge(6, 5);
g.addEdge(6, 7);
g.addEdge(7, 3);
g.addEdge(7, 4);
g.addEdge(7, 6);
g.addEdge(8, 1);
g.addEdge(8, 2);
g.addEdge(8, 3);
System.out.println("深度优先遍历(非递归):");
g.DFSTraverse();
System.out.println();
System.out.println("深度优先遍历(递归):");
g.DFSTraverse1();
}
}