图的深度优先遍历
遍历图的节点
一般有两种策略:
1.深度优先遍历
2.广度优先遍历
深度优先遍历的基本思想:
1.从初始访问节点出发,初始访问节点可能有多个邻接节点,深度优先遍历就是有可能有多个邻接节点,然后在以后访问的节点作为初始节点,访问它的初始邻接节点,访问它的第一个邻接节点,可以理解为:每次访问的是当前节点的第一个邻接节点
2.我们可以看到,这样的访问策略是优先级纵向挖掘深入,而不是对一个节点的所有邻接节点进行横向遍历
3.显然,深度优先遍历是一个递归的过程
步骤
1.访问初始化节点v,并标记节点v为已访问。
2.查找节点v的第一个邻接节点w
3.若w存在,继续执行4,如果不存在,则回到第一步,将从v的下一个节点继续
4.若w未被访问,对w进行深度优先遍历递归(即把w当成另一个v,然后进行123步骤)
5.查找节点v的w邻接节点的下一个邻接节点,转到步骤3
代码实现
package com.zou.graph;
import java.util.ArrayList;
import java.util.Arrays;
public class Graph {
private ArrayList<String> vertexList;//存储顶点集合
private int[][] edges;//存储邻接矩阵的边
private int numOfEdges;//表示边的数目
//定义一个boolean[],记录某个节点是否被访问过
private boolean[] isVisited;
public static void main(String[] args) {
//节点个数
int n=5;
String Vertexs[]={"A","B","C","D","E"};
//创建图对象
Graph graph = new Graph(n);
//循环添加
for (String vertex : Vertexs) {
graph.insertVertex(vertex);
}
//添加边
//A-B A-C B-C B-D B-E
graph.insertEdge(0,1,1);
graph.insertEdge(0,2,1);
graph.insertEdge(1,2,1);
graph.insertEdge(1,3,1);
graph.insertEdge(1,4,1);
//显示邻接矩阵
graph.showGraph();
//深度遍历
System.out.println("深度遍历");
graph.dfs();
}
//构造器
public Graph(int n) {//n:顶点
//初始化矩阵图和顶点
edges=new int[n][n];
vertexList = new ArrayList<String>(n);//顶点
numOfEdges=0;//初始化边的数目
isVisited = new boolean[5];
}
//得到第一个邻接节点下标
/**
*
* @param index
* @return 返回存在就返回对应下标,否则返回-1
* @author yuxin
* @creed: Talk is cheap,show me the code
* @date
*/
public int getFirstNeighbor(int index){
for (int i = 0; i < vertexList.size(); i++) {
if (edges[index][i]>0){
return i;
}
}
return -1;
}
//根据前一个邻接节点获取下一个邻接节点
public int getNextNeighbor(int v1,int v2){
for (int i = v2+1; i < vertexList.size(); i++) {
if (edges[v1][1]>0){
return i;
}
}
return -1;
}
//深度优先遍历
//i第一次就是0
private void dfs(boolean[] isVisited,int i){
//首先我们将访问该节点输出
System.out.print(getValueByIndex(i)+"->");
//设置已访问
isVisited[i]=true;
//查找节点i的第一个邻接节点w
int w = getFirstNeighbor(i);
while(w!=-1){ //说明有
if (!isVisited[w]){
dfs(isVisited,w);
}
//如果w节点已经被访问过
w=getNextNeighbor(i,w);
}
}
//对dfs进行重载,遍历我们所有的节点,进行递归
public void dfs(){
//遍历所有的节点,进行dfs
for (int i = 0; i < getNumOfVertex(); i++) {
if (!isVisited[i]){
dfs(isVisited,i);
}
}
}
//常用方法
//返回点的个数
public int getNumOfVertex(){
return vertexList.size();
}
//显示矩阵
public void showGraph(){
for (int[] link : edges) {
System.err.println(Arrays.toString(link));
}
}
//返回边数
public int getNumOfEdges(){
return numOfEdges;
}
//返回节点i下标对应的数据0->"A" 1->"B" 2->"C"
public String getValueByIndex(int i){
return vertexList.get(i);
}
//返回v1和v2的权值
public int getWeight(int v1,int v2){
return edges[v1][v2];
}
//插入节点
public void insertVertex(String vertex){
vertexList.add(vertex);
}
//添加边
public void insertEdge(int v1,int v2,int weight){
edges[v1][v2]=weight;
edges[v2][v1]=weight;
numOfEdges++;
}
}
结果
邻接矩阵
[0, 1, 1, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
深度遍历
A->B->C->D->E->
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库