从零开始学数据结构系列之第四章《 图的遍历之深度优先遍历》


图的遍历

​ 图的遍历是和树的遍历类似,我们希望从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次, 这一过程就叫做图的遍历(Traversing Graph)。
​ 对于图的遍历来,通常有两种遍历次序方案:它们是深度优先遍历和广度优先遍历。

深度优先遍历(DFS)

概念

深度优先遍历(Depth First Search),也有称为深度优先搜索,简称为DFS

​ 深度优先搜索类似于树的先序遍历。如其名称中所暗含的意思一样,这种搜索算法所遵循的搜索策略是尽可能“深”地搜索一个图。它的基本思想如下:首先访问图中某一起始顶点v,然后由v出发,访问与v邻接且未被访问的任一顶点,再访问与邻接且未被访问的任一顶点,重复上述过程。当不能再继续向下访问时,依次退回到最近被访问的顶点,若它还有邻接顶点未被访问过,则从该点开始继续上述搜索过程,直至图中所有顶点均被访问过为止。

​ 简单来说就是:

这种遍历方式主要思路是从图中一个未访问的顶点V开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底,不断递归重复此过程,直到所有的顶点都遍历完成。它的特点是不撞南墙不回头,先走完一条路,再换一条路继续走。

​ 有个简单的口诀可以方便记忆:

一条路走到黑
不到南墙不回头撞墙之后再回头
回头之后再撞墙
直到无墙可撞为止

图的深度优先遍历

深度优先遍历,从初始访问结点出发,初始访问节点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点,可以这样理解:每次都在访问完当前结点后首先访问当前的第一个邻接结点
我们可以看到,这样的访问策略是优先纵向挖掘深入,而不是对一个结点的所有邻接结点进行横向访问
显然,深度优先搜索是一个递归的过程

深度优先遍历算法步骤

  1. 访问初始结点 v,并标记结点 v 为已访问
  2. 查找结点 v 的第一个邻接结点 w
  3. 若 w 存在,则继续访问 4,如果 w 不存在,则回到第 1 步,将从 v 的下一个结点继续
  4. 若 w 未被访问,对 w 进行深度优先遍历递归(即把 w 当作另一个 v ,然后进行步骤 123)
  5. 查找结点 v 的 w 邻接结点的下一个邻接结点,转到步骤 3

我们用的是以下这张图:
在这里插入图片描述

总代码

代码如下:

/*
*	visited	-存放标志位的数组
*	index - 遍历的行数
*/
void DFS(Graph* G, int* visited, int index) 
{
	int i=0;
	printf("%c ",G->vexs[index]);
	visited[index] = 1;
	for(i=0;i<G->vexNum;i++)
	{
        // 如果是未撞南墙同时不是之前撞过的南墙
		if(G->arcs[index][i] && !visited[i])
			DFS(G,visited,i);
	}
}

遍历过程如下:

<1> 此时由A到B,发现A有到B的边,则遍历到B处,B可以输出

<1>ABCDE
A0110
B10111
C11000
D11001
E01010

**<2>**由B继续往后遍历,B有到C的边,则C可以输出

<2>ABCDE
A01110
B1011
C11000
D11001
E01010

**<3>**到C顶点处,没有下一个未访问的顶点了,正常来说按顺序是到D的,结果C到D没有边,则递归返回到B顶点,由B继续走未走过的边遍历未访问的顶点,于是到了D顶点,D输出

<3>ABCDE
A01110
B1011
C11000
D11001
E01010

**<4>**D继续往后走,发现到E有路了,于是E输出

<4>ABCDE
A01110
B10111
C11000
D1100
E01010

总结:

通过以上的图像分步遍历示意,同学们应该知道规律了。找下一个相邻顶点时看行,有没有边看行列相交处是否为1,有边是1,无边为0。

往期回顾

1.【第一章】《线性表与顺序表》
2.【第一章】《单链表》
3.【第一章】《单链表的介绍》
4.【第一章】《单链表的基本操作》
5.【第一章】《单链表循环》
6.【第一章】《双链表》
7.【第一章】《双链表循环》
8.【第二章】《栈》
9.【第二章】《队》
10.【第二章】《字符串暴力匹配》
11.【第二章】《字符串kmp匹配》
12.【第三章】《树的基础概念》
13.【第三章】《二叉树的存储结构》
14.【第三章】《二叉树链式结构及实现1》
15.【第三章】《二叉树链式结构及实现2》
16.【第三章】《二叉树链式结构及实现3》
17.【第三章】《二叉树链式结构及实现4》
18.【第三章】《二叉树链式结构及实现5》
19.【第三章】《中序线索二叉树理论部分》
20.【第三章】《中序线索二叉树代码初始化及创树》
21.【第三章】《中序线索二叉树线索化及总代码》
22【第三章】《先序线索二叉树理论及线索化》
23【第三章】《先序线索二叉树查找及总代码》
24【第三章】《后续线索二叉树线索化理论》
25【第三章】《后续线索二叉树总代码部分》
26【第三章】《二叉排序树基础了解》
27【第三章】《二叉排序树代码部分》
28【第三章】《二叉排序树代码部分》
29【第三章】《平衡二叉树基础概念》
30【第三章】《平衡二叉树的平衡因子》
31【第三章】《平衡二叉树的旋转基础详解》
32【第三章】《平衡二叉树的旋转类型图文详解》
33【第三章】《平衡二叉树的旋转类型总结及总代码》
34【第三章】《哈夫曼树简单了解》
35【第三章】《哈夫曼树的构造方法》
36【第三章】《哈夫曼编码构造及代码》
37【第三章】《图的定义》
38【第三章】《图的基本概念和术语》
39【第三章】《图的存储结构》

  • 32
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值