图的深度优先遍历(Depth First Search)

基本思想

类似于二叉树的先序遍历

  1. 假设图中所有结点均未被访问,从初始结点访问,访问其第一个邻接结点,接着以被访问的邻接结点作为初始结点,访问它的第一个邻接结点。

  2. 递归的过程。

算法步骤

  1. 访问初始结点v,并标记为已访问

  2. 查找结点v的第一个邻接结点w

  3. 若w存在,则继续执行4,若不存在则回到第1步,从v的下一个结点继续

  4. 若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v,然后进行步骤123)

  5. 查找结点v的邻接结点w的下一个邻接结点,转到步骤3

无向图深度优先遍历演示

1. 访问A

2. 访问(A的邻接点)C
   在第1步访问A之后,接下来应该访问的是A的邻接点,即"C,D,F"中的一个。但在本文的实现中,顶点ABCDEFG是按照顺序存储,C在"D和F"的前面,因此,先访问C。

3. 访问(C的邻接点)B
   在第2步访问C之后,接下来应该访问C的邻接点,即"B和D"中一个(A已经被访问过,就不算在内)。而由于B在D之前,先访问B。

4. 访问(C的邻接点)D
   在第3步访问了C的邻接点B之后,B没有未被访问的邻接点;因此,返回到访问C的另一个邻接点D。

5. 访问(A的邻接点)F
   前面已经访问了A,并且访问完了"A的邻接点C的所有邻接点(包括递归的邻接点在内)";因此,此时返回到访问A的另一个邻接点F。

6. 访问(F的邻接点)G

7. 访问(G的邻接点)E

因此访问顺序是:A -> C -> B -> D -> F -> G -> E

有向图深度优先遍历演示

1. 访问A

2. 访问B
   在访问了A之后,接下来应该访问的是A的出边的另一个顶点,即顶点B。

3. 访问C
   在访问了B之后,接下来应该访问的是B的出边的另一个顶点,即顶点C,E,F。在本文实现的图中,顶点ABCDEFG按照顺序存储,因此先访问C。

4. 访问E
   接下来访问C的出边的另一个顶点,即顶点E。

5. 访问D
   接下来访问E的出边的另一个顶点,即顶点B,D。顶点B已经被访问过,因此访问顶点D。

6. 访问F
   访问D之后,出边顶点C已访问;回溯到E,E的出边顶点BD均访问;依次回溯到B,B的出边顶点CF中F未访问,所以访问F。

7. 访问G

因此访问顺序是:A -> B -> C -> E -> D -> F -> G

算法实现

import java.util.ArrayList;
import java.util.Arrays;public class GraphTraversal {private ArrayList<Object> nodeList;//存储结点的集合private int[][] edges;//结点与结点之间的连线关系private int numOfEdges;//图中连线数量private boolean[] isVisited;//标记结点是否被访问public GraphTraversal(int n){//初始化矩阵和顶点列表nodeList = new ArrayList<Object>(n);edges = new int[n][n];numOfEdges = 0;isVisited = new boolean[n];}public static void main(String[] args) {//声明图中结点int n = 7;String nodes[] = {"A","B","C","D","E","F","G"};//创建一个无向图GraphTraversal undirectedGraph = new GraphTraversal(n);//将顶点添加到图中if(undirectedGraph.addNodes(nodes) > 0){//添加顶点间的关系undirectedGraph.insertUndirectedEdge(0, 3, 1);undirectedGraph.insertUndirectedEdge(0, 2, 1);undirectedGraph.insertUndirectedEdge(0, 5, 1);undirectedGraph.insertUndirectedEdge(2, 1, 1);undirectedGraph.insertUndirectedEdge(2, 3, 1);undirectedGraph.insertUndirectedEdge(5, 6, 1);undirectedGraph.insertUndirectedEdge(6, 4, 1);//显示邻接矩阵System.out.println("无向图邻接矩阵:");undirectedGraph.showGraph();//无向图深度优先遍历System.out.println("无向图深度优先遍历:");undirectedGraph.dfs();}//创建一个有向图GraphTraversal directedGraph = new GraphTraversal(n);//添加结点到图中if (directedGraph.addNodes(nodes) > 0){//添加结点之间的关系directedGraph.insertDirectedEdge(0,1,1);directedGraph.insertDirectedEdge(1,2,1);directedGraph.insertDirectedEdge(1,4,1);directedGraph.insertDirectedEdge(1,5,1);directedGraph.insertDirectedEdge(2,4,1);directedGraph.insertDirectedEdge(3,2,1);directedGraph.insertDirectedEdge(4,3,1);directedGraph.insertDirectedEdge(4,1,1);directedGraph.insertDirectedEdge(5,6,1);//显示邻接矩阵System.out.println("有向图邻接矩阵:");directedGraph.showGraph();//有向图深度优先遍历System.out.println("有向图深度优先遍历:");directedGraph.dfs();}}//将结点添加到图中public int addNodes(Object[] nodes){for (Object node : nodes){nodeList.add(node);}return nodeList.size();}//创建无向图结点关系public void insertUndirectedEdge(int v1, int v2, int weight){edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}//创建有向图结点关系public void insertDirectedEdge(int v1, int v2, int weight){edges[v1][v2] = weight;numOfEdges++;}//显示邻接矩阵public void showGraph(){for (int[] link : edges){System.out.println(Arrays.toString(link));}}//根据初始结点获取第一个邻接结点public int getFirstNeighbor(int v1){for(int v2 = 0; v2 < edges.length; v2++){if (edges[v1][v2] > 0){return v2;}}return -1;}//根据前一个邻接结点获取下一个邻接结点public int getNextNeighbor(int v1, int v2){for (int j = v2 + 1; j < edges.length; j++){//从上一个结点[v1]开始找下一个结点if (edges[v1][j] > 0){//若 v1 到 j 的连线存在,则存在下一个结点return j;}}return -1;//说明不存在下一个结点}//dfs深度优先遍历public void dfs(boolean[] isVisited, int v){//输出当前访问的起始结点System.out.print(nodeList.get(v) + "->");//根据索引值获取List中结点值//当前起始结点标记为已访问isVisited[v] = true;//访问起始结点的第一个邻接结点int w = getFirstNeighbor(v);while (w != -1){//说明存在第一个邻接结点if (!isVisited[w]){//未被标记为已访问dfs(isVisited, w);//把当前的邻接结点作为起始结点,递归执行深度遍历算法}//如果w结点已经被访问,则寻找下一个邻接结点w = getNextNeighbor(v, w);}}//对 dfs 重载,使其对所有结点进行 dfspublic void dfs(){for (int i = 0; i < nodeList.size(); i++){if (!isVisited[i]){//结点未被标记为已访问dfs(isVisited, i);//第 i 个结点作为初始结点进行 dfs}}System.out.println();}
}

图的深度优先遍历(Depth First Search)相关推荐

  1. 深度优先遍历(Depth First Search, 简称 DFS)

    正文开始: 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷 ...

  2. 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构|图的邻接表与深度、广度优先搜索

    线性存储元素时,元素的关系也同时确定了.而非线性数据结构就不同了,需要同时考虑存储数据元素和数据元素的关系. 由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位 ...

  3. 实验报告C语言实现图的深度遍历,图的深度优先遍历的C语言实现.pdf

    图的深度优先遍历的C语言实现.pdf 维普资讯 九 江 职 业 技 术 学 院 学 报 JournalofJiujiangVocational&TechnicalCollege 2004.2 ...

  4. 数据结构 图的深度优先遍历 C

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Bool ...

  5. java语言实现图的深度优先遍历

    java语言实现图的深度优先遍历: 图的存储采用的是邻接矩阵存储的方式,对下面的无向图进行遍历 代码如下: public class Deep {int count=0;public static v ...

  6. 广度优先搜索生成树怎么画_图的深度优先遍历与广度优先遍历以及最小生成树...

    图的深度优先遍历 题目:写出附从每个顶点出发的一次深度优先搜索遍历序列.在纸上画出遍历过程和序列,提交截图. 错误回答 从A点开始遍历:0124-01324-0134-0324-034 从B点开始遍历 ...

  7. C++实现图的深度优先遍历和广度优先遍历

    图的深度和广度优先遍历 图的深度优先遍历 1.算法思想 2.邻接矩阵构造图 3.邻接表构造图 图的广度优先遍历 1.算法思想 2.邻接矩阵构造图 图的深度优先遍历 1.算法思想 (1)从图中的某个初始 ...

  8. 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构与算法学习笔记:图...

    图: 图结构区别于线性结构和树型结构,区别可见下图 逻辑上的图(graph)结构由顶点(vertex)和边(edge)组成. 一个图结构G包含顶点集合V和边集合E,任何两个顶点之间可以有一个边表示两者 ...

  9. 邻接矩阵存储图的深度优先遍历

    练习6.1 邻接矩阵存储图的深度优先遍历 (20 分) 试实现邻接矩阵存储图的深度优先遍历. 函数接口定义: void DFS( MGraph Graph, Vertex V, void (*Visi ...

最新文章

  1. kubernetes Helm
  2. Python的浅拷贝和深拷贝
  3. android动态jar,Android动态加载Jar(包含第三方依赖Jar)
  4. 【Ubuntu-apt-换源】ubuntu系统换源后使用apt-get update时一直0%[执行中]
  5. [Java基础]Object类的常用方法
  6. opencv:灰色和彩色图像的像素直方图及直方图均值化的实现与展示
  7. 如何获得Windows聚焦壁纸0726
  8. JavaSE基础笔记十二
  9. Ubuntu13.04配置优化(四)转贴
  10. Cocos2dx游戏源码合集
  11. 全网最全sql入门经典
  12. 代码整洁之道-编写 Pythonic 代码
  13. java数据类型简介
  14. Linux虚拟机挂载新的硬盘
  15. word查重_2020论文查重倾情分享 | 查重注意要点
  16. 为什么微信无法打开html文件,微信网页版打不开怎么办?微信网页版无法打开的解决方法...
  17. android qq音乐无法连接网络连接,qq音乐不能播放_qq音乐为什么老是提示说歌曲无效或网络连接失败呢?...
  18. export default function和export function的区别
  19. Android Device Moniter部分问题的解决办法:
  20. HDU-圆桌会议问题

热门文章

  1. 状态迁移法你还不会?看看这篇文章
  2. Java语言高级(第一部分)常用API 继承与多态 ->(个人学习记录笔记)
  3. SSM整合(Spring + SpringMVC + Mybatis)
  4. 激光清洗机能清洗什么
  5. 【OpenCV案例实战分享】关于图像处理的一些基本操作之二值化、图像加噪处理......
  6. 我的世界服务器自建主城,为纪念去世的服务器创建人,《我的世界》玩家们竖起了告示牌...
  7. 360安全路由开启预约 双频路由器售价99元
  8. 4.1 keras基础实例 手写数字识别
  9. EL表达式判断Map是否为空和map的取值
  10. C语言程序设计(本) 阶段作业,武汉理工大学继续教育《C语言程序设计(本)》在线作业答案...