分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_图搜索

本文详细介绍了如何使用邻接矩阵和邻接表实现图的深度优先搜索(DFS)和广度优先搜索(BFS)。深度优先遍历利用栈实现,广度优先遍历利用队列实现,通过实例展示了两种遍历方法的过程,并分析了算法的时间复杂度。

ce6b5931097a677076cdf79b5568506f.png

目录:

  • 深度优先搜索
  • 广度优先搜索

深度优先搜索:

深度优先搜索(Depth First Search,DFS),是最常见的图搜索方法之一。深度优先搜索沿着一条路径一直走下去,无法行进时,回退到刚刚访问的结点。深度优先遍历是按照深度优先搜索的方式对图进行遍历。

深度优先遍历秘籍:后被访问的顶点,其邻接点先被访问。

根据深度优先遍历秘籍,后来先服务,可以借助于栈实现。递归本身就是使用栈实现的,因此使用递归方法更方便。

算法步骤:

  1. 初始化图中所有顶点未被访问。
  2. 从图中的某个顶点v出发,访问v并标记已访问;
  3. 依次检查v的所有邻接点w,如果w未被访问,则从w出发进行深度优先遍历(递归调用,重复2—3步)。

以图1为例,进行图深度优先搜索理解:

362a59d192bed55d1098702ac7ea3c7f.png
图1.深度优先搜索

step1:如图2,访问结点1;

4bb9dabd80fe80ef6f49040e8d78c29c.png
图2.深度优先搜索

step2:如图3,访问结点1的邻接点2,然后访问邻接点2的邻接点4,再访问邻接点4的邻接点5;

d8fe932e3967b2b92e8e2dbf9c3c2086.png
图3.深度优先搜索

step3:如图4,结点5没有未访问的邻接点了,然后回退到结点4,结点4也没有未被访问的邻接点,继续回退到结点2,结点2有未被访问的邻接点6,则访问邻接点6;

70109cda4d58760cb24077f63e11b916.png
图4.深度优先搜索

step4:如图5,结点6没有未被访问的邻接点,则回退到结点2,结点也没有未被访问的邻接点,回退到结点1;

9fde29a36ae943c59c3bae8f2c263280.png
图5.深度优先搜索

step5:如图6,结点1存在未被访问的邻接点,则访问邻接点3,邻接点存在未被访问的邻接点7则访问邻接点7,邻接点存在未被访问的邻接点8,则访问邻接点8;

bde6cd0eca078ed291b9b2372a635df5.png
图6.深度优先搜索

step6:如图7,结点8不存在未被访问的邻接点,故回退到结点7,结点7不存在未被访问的邻接点,故回退到结点3,结点3不存在未被访问的邻接点,故回退到结点1,结点不存在违背访问的邻接点,故深度优先遍历结束。

51a96e8a91f2805feaaa25bb7e6a8687.png
图7.深度优先搜索

最终,去掉没有深度优先没有经过的路径,可得如图8,深度优先生成树;

98ee82fca969d5fc557797cbf3b1c670.png
图8.深度优先生成树

代码:

void 

算法分析:

1.基于邻接矩阵的DFS算法

查找每个顶点的邻接点需要O(n)时间,一共n个顶点,总的时间复杂度为

,使用了一个递归工作栈,空间复杂度为
O(n)。

2.基于邻接表的DFS算法

查找顶点

的邻接点需要
时间,
的出度(无向图为度),对有向图而言,所有顶点的出度之和等于边数
e,对无向图而言,所有顶点的度之和等于2e,因此查找邻接点的时间复杂度为O(e),加上初始化时间O(n),总的时间复杂度为O(n+e),使用了一个递归工作栈,空间复杂度为O(n)。

广度优先搜索:

广度优先搜索(Breadth First Search,BFS),又称为宽度优先搜索,是最常见的图搜索方法之一。广度优先搜索是从某个顶点(源点)出发,一次性访问所有未被访问的邻接点,再依次从这些访问过邻接点出发。广度优先遍历是按照广度优先搜索的方式对图进行遍历,如图9。

8d42483052ca6924ab03002b5f1d6f3f.png
图9.广度优先遍历

7d336dacf7fde67ae7ead4adf241639f.png

广度优先遍历秘籍:先被访问的顶点,其邻接点先被访问。

根据广度优先遍历秘籍,先来先服务,可以借助于队列实现。每个结点访问一次且只访问一次,因此可以设置一个辅助数组:

visited[i]=false,表示第i个顶点未访问;

visited[i]=true,表示第i个顶点已访问。

算法步骤:

  1. 初始化图中所有顶点未被访问,初始化一个空队列。
  2. 从图中的某个顶点v出发,访问v并标记已访问,将v入队;
  3. 如果队列非空,则继续执行,否则算法结束;
  4. 队头元素v出队,依次访问v的所有未被访问邻接点,标记已访问并入队。转向步骤3;

以图10为例,进行图深度优先搜索理解:

228431302ea94feaec79b107f8bc66c1.png
图10.广度优先遍历

step1:如图11,从图结点1开始访问,将结点1入队,同时visit[1]=True;

139eb343b5a7b92bfab326c4ca32274e.png
图11.广度优先搜索

step2:如图12,结点1出队,访问结点1的邻接点2和3,将结点2和结点3入队;

d470e3f346e405d14a55f2c51f4a8bce.png
图12.广度优先搜索

step3:如图13,结点2出队,访问2的邻接点4,将结点4入队;

c47d76048aabbbdebbec268ff119d419.png
图13.广度优先搜索

step4:如图14,结点3出队,访问3的邻接点5,将结点5入队;

afcf66c5a7c36fb160168722482f70d4.png
图14.广度优先搜索

step5:如图15,结点4出队,访问结点4的邻接点6,邻接点6入队;

534e55bece273dd2df408dd4ac4b3cd9.png
图15.广度优先搜索

step6:如图16,至此,所有节点都被访问,去掉未经过的边,得到广度优先生成树;

31ba7dea98ced88f9becc322a031f5a6.png
图16.广度优先生成树

算法分析:

1.基于邻接矩阵的BFS算法

查找每个顶点的邻接点需要O(n)时间,一共n个顶点,总的时间复杂度为

,使用了一个辅助队列,最坏的情况下每个顶点入队一次,空间复杂度为
O(n)。

2.基于邻接表的BFS算法

查找顶点vi的邻接点需要

时间,
vi的出度(无向图为度),对有向图而言,所有顶点的出度之和等于边数e,对无向图而言,所有顶点的度之和等于2e,因此查找邻接点的时间复杂度为O(e),加上初始化时间O(n),总的时间复杂度为O(n+e),使用了一个辅助队列,最坏的情况下每个顶点入队一次,空间复杂度为O(n)。
void 

深度优先搜索:

邻接矩阵存储图:

https://github.com/xinhai2017/Data-Structures-and-Algorithms/blob/master/9.1.DFS_AM.cpp​github.com

邻接表存储图:

https://github.com/xinhai2017/Data-Structures-and-Algorithms/blob/master/9.2.DFS_AL.cpp​github.com

广度优先搜索:

邻接矩阵存储图:

https://github.com/xinhai2017/Data-Structures-and-Algorithms/blob/master/9.3.BFS_AM.cpp​github.com

邻接表存储图:

https://github.com/xinhai2017/Data-Structures-and-Algorithms/blob/master/9.4.BFS_AL.cpp​github.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值