欢迎移步博主CSDN:[CSDN博客](https://blog.csdn.net/weixin_42327790/article/details/103120803) # 无向图的两种遍历算法的实现 ## 简介 图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为 $$ G = (V,E) $$ 如果图的任意两个顶点之间的边都是无向边,则称该图为**无向图**,否则称该图为**有向图**。 ## 图的两种遍历算法思想 * 深度优先遍历算法思想 (1)访问顶点v; (2)从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历; (3)重复上述两步,直至图中所有和v有路径相通的顶点都被访问到 * 广度优先遍历算法思想 (1)访问顶点v; (2)依次访问v的各个未被访问的邻接点v1,v2,v3...... (3)分别从v1,v2,v3......出发依次访问它们未被访问的邻接点,并使先被访问顶点的邻接点先于后被访问顶点的邻接点被访问。直至图中所有与顶点v有路径相通的顶点都被访问到。 ## 采用邻接矩阵存储 图的邻接矩阵存储也称为数组表示法,其方法是用一个以为数组存储图中顶点的信息,用一个二维数组存储图中边的信息,存储顶点之间临界关系的二维数组称为邻接矩阵。 --- 以下面这个无向图为例进行实现  * 该无向图的`DFS`访问顺序:V0->V1->V4->V5->V2->V3 * 该无向图的`BFS`访问顺序:V0->V1->V2->V3->V4->V5 为了省时间(~~其实是自己懒~~ ),此处省略邻接矩阵的构造过程,采用手动写入边集和点集构建该无向图。 ```java //手动构造图的点集和边集 //点集 int[] vector = { 0,1,2,3,4,5 }; //边集 int[][] arc ={ {0,1,1,1,1,0}, {1,0,0,0,1,0}, {1,0,0,0,1,0}, {1,0,0,0,0,0}, {1,1,1,0,0,1}, {0,0,0,0,1,1} }; //记录是否访问 int[] visited = { 0,0,0,0,0,0 }; ``` ### 深度优先遍历(递归实现) ```java //图的深搜DFS,递归 public static void DFS(int[] vector, int[] visited, int[][] arc,int i){ //访问结点并标记 System.out.println(vector[i]); visited[i]=1; for (int j = 0;j stack = new Stack(); stack.push(0); visited[0] = 1; while(!stack.isEmpty()){ //获取栈顶元素 int x = stack.peek(); //标志位 boolean flag = false; for (int i = 0; i queue = new LinkedList(); //第一个顶点入队 queue.offer(0); while (!queue.isEmpty()){ //出队 int x = queue.poll(); //访问结点并标记 System.out.println(vector[x]); visited[x] = 1; //寻找连通的结点并入队 for (int i = 0; iV1->V4->V2->V3 * 该无向图的`BFS`访问顺序:V0->V1->V2->V3->V4 为了省时间(~~其实是自己懒~~ ),此处省略邻接表的构造过程,采用手动写入边集和点集构建该无向图。 ```java //手动构造图的点集和边集 //手动构造点集和边集 VertexNode[] vertex = new VertexNode[5]; for (int i = 0;i stack = new Stack(); //访问第一个顶点并入栈 System.out.println(vertex[0].vertex); stack.push(0); visited[0]=1; //栈不为空 while(!stack.isEmpty()){ boolean flag = false; //获取栈顶但不弹栈 int i = stack.peek(); ArcNode tmp = vertex[i].firstEdge; //遍历边表 while(tmp!=null){ if (visited[tmp.adjvex]==0){ //访问并入栈 System.out.println(vertex[tmp.adjvex].vertex); stack.push(tmp.adjvex); //更改访问位,标志位 visited[tmp.adjvex]=1; flag = true; break; } tmp = tmp.next; } //弹栈 if(!flag) stack.pop(); } } ``` ### 广度优先遍历 ```java /** * @Description: 图的广搜BFS,邻接矩阵存储,非递归 * @Param: [vertex, visited] * @return: void * @Author: zbl * @Date: 2019/11/18 */ public static void BFS(VertexNode[] vertex,int[] visited){ for (int i = 0; i stack = new Stack(); stack.push(0); visited[0] = 1; while(!stack.isEmpty()){ //获取栈顶元素 int x = stack.peek(); //标志位 boolean flag = false; for (int i = 0; i queue = new LinkedList(); //第一个顶点入队 queue.offer(0); while (!queue.isEmpty()){ //出队 int x = queue.poll(); //访问结点并标记 System.out.println(vector[x]); visited[x] = 1; //寻找连通的结点并入队 for (int i = 0; i stack = new Stack(); //访问第一个顶点并入栈 System.out.println(vertex[0].vertex); stack.push(0); visited[0]=1; //栈不为空 while(!stack.isEmpty()){ boolean flag = false; //获取栈顶但不弹栈 int i = stack.peek(); ArcNode tmp = vertex[i].firstEdge; //遍历边表 while(tmp!=null){ if (visited[tmp.adjvex]==0){ //访问并入栈 System.out.println(vertex[tmp.adjvex].vertex); stack.push(tmp.adjvex); //更改访问位,标志位 visited[tmp.adjvex]=1; flag = true; break; } tmp = tmp.next; } //弹栈 if(!flag) stack.pop(); } } /** * @Description: 图的深搜DFS,邻接矩阵存储,递归 * @Param: [vertex, visited, i] * @return: void * @Author: zbl * @Date: 2019/11/18 */ public static void DFS(VertexNode[] vertex,int[] visited,int i){ System.out.println(vertex[i].vertex); visited[i]=1; ArcNode tmp = vertex[i].firstEdge; while(tmp != null){ int j = tmp.adjvex; if(visited[j]==0) DFS(vertex,visited,j); tmp = tmp.next; } } /** * @Description: 图的广搜BFS,邻接矩阵存储,非递归 * @Param: [vertex, visited] * @return: void * @Author: zbl * @Date: 2019/11/18 */ public static void BFS(VertexNode[] vertex,int[] visited){ for (int i = 0; i 最后修改:2020 年 03 月 14 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏
1 条评论
文章结构紧凑,层次分明,逻辑严密,让人一读即懂。