【数据结构】图的遍历(BFS和DFS)
图的遍历
图的遍历是指从图中的某一顶点出发,按照某种搜索方式沿着途中的边对图中所有顶点访问一次且仅访问一次。图的遍历主要有两种算法:广度优先搜索和深度优先搜索。
广度优先遍历BFS
广度优先遍历(BFS 也叫广度优先搜索)类似于二叉树的层序遍历算法
#define MaxSize 100;
bool visited[MaxSize]; //访问数组,记录顶点是否被访问过,初始都赋值为false
void BFS(Graph G,int v){ //图用邻接表存储,从下标为v的位置开始遍历ArcNode *p; //工作指针pInitQueue(Q); //初始化一个队列visit(v); //访问第一个顶点v 具体可以是Print visited[v]=TRUE; //对v做已访问标记Enqueue(Q,v); //顶点v入队列while(!isEmpty(Q)){ //只要队列不空DeQueue(Q,v); //顶点v出队列p=G->adjList[v].firstedge; //指针p指向当前顶点的边表链表头指针while(p){ if(!visited[p->adjvex]){ //p所指向顶点如果未被访问 visit(p->adjvex); //访问p所指向的顶点visited[p->adjvex]=TRUE; //对这个顶点做已访问标记EnQueue(Q,p->adjvex); //这个顶点入队列} p=p->next; //p指向该顶点的下一条边}}
}
void BFSTraverse(Graph G){int i; //单独定义是为了方便多个循环中使用for(i=0; i<G->vexnum; i++)visited[i]=false; //将标志数组初始化 (全局数组)for(i=0; i<G->vexnum; i++){ if(!visited[i])BFS(G,i);} //为了避免非连通图一些顶点访问不到 若是连通图只会执行一次}
}
BFS复杂度分析
- 不论是邻接表还是邻接矩阵的存储方式,BFS算法都需要借助一个辅助队列Q,n个顶点均需入队一次,在最坏的情况下,空间复杂度为O(∣V∣)O(|V|)O(∣V∣)。
- 当采用邻接表存储方式时,每个顶点均需要搜索一次(或者入队一次)姑时间复杂度为O(∣V∣)O(|V|)O(∣V∣),在搜索任意一顶点的临接点时,每条边需要访问一次,故时间复杂度为O(∣E∣)O(|E|)O(∣E∣)。算法的总时间复杂度为O(∣V∣+∣E∣)O(|V|+|E|)O(∣V∣+∣E∣)。
- 当采用邻接矩阵存储方式时,查找每个顶点的临接点所需的时间为O(∣V∣)O(|V|)O(∣V∣),故算法的时间复杂度为O(∣V∣2)O(|V|^2)O(∣V∣2)。
BFS应用
BFS解决单源非带权图最短路径问题:按照距离由近到远来遍历图中每个顶点
void BFS_MIN_Distance(Graph G,int u){ //d[i]表示从u到i结点的最短路径for(i=0;i<G.vexnum;++i) d[i]=∞; //初始化路径长度visited[u]=TRUE; d[u]=0;EnQueue(Q,u);while(!isEmpty(Q)){ DeQueue(Q,u); ArcNode *p=G->adjList[u].firstedge; while(p){ If(!visited[p->adjvex]){ visited[p->adjvex]=TRUE; //路径长度加1 d[p->adjvex]=d[u]+1; EnQueue(Q, p->adjvex); } p=p->next;}}
}
广度优先生成树
深度优先遍历DFS
深度优先遍历(DFS:Depth-First-Search):深度优先遍历类似于树的先序遍历算法
首先访问图中某一起始顶点v,然后由v出发,访问与v邻接且未被访问的任一顶点w1,再访问与w1邻接且未被访问的任一顶点w2,……重复上述过程。当不能再继续向下访问时,依次退回到最近被访问的顶点,若它还有邻接顶点未被访问过,则从该点开始继续上述搜索过程,直到图中所有顶点均被访问过为止
#define MaxSize 100;
bool visited[MaxSize];
void DFS(Graph G,int v){ArcNode *p; //工作指针pvisit(v); //访问顶点v(一般是打印,即printf)visited[v]=TRUE; //修改访问标记p=G->adjlist[v].firstarc; //指针p开始指向该顶点的第一条边while(p!=NULL){ //没遍历完顶点的所有邻接顶点if(!visited[p->adjvex]){ //如果该顶点没被访问DFS(G,p->adjvex); //递归访问该顶点} p=p->nextarc; //看还有没有其他未访问的顶点
}
void DFSTraverse(Graph G){int i; //单独定义是为了方便多个循环中使用for(i=0; i<G->vexnum; i++)visited[i]=false; //将标志数组初始化 (全局数组)for(i=0; i<G->vexnum; i++){ if(!visited[i]) DFS(G,i); //对所有
}
DFS算法是一个递归算法,需要借助一个递归工作栈,故她的空间复杂度为O(∣V∣)O(|V|)O(∣V∣)。
遍历图的过程实质上是对每个顶点查找其临接点的过程,其耗费的时间取决于所采用的存储结构。
- 当以邻接表表示时,查找所有顶点的临接点所需时间为O(∣E∣)O(|E|)O(∣E∣),访问顶点所需时间为O(V)O(V)O(V),此时,总的时间复杂度为O(∣V∣+∣E∣)O(|V|+|E|)O(∣V∣+∣E∣)。
- 当以邻接矩阵进行表示时,查找每个顶点的邻接点所需时间为O(∣V∣)O(|V|)O(∣V∣),故总的时间复杂度为O(∣V∣2)O(|V|^2)O(∣V∣2)。
深度优先生成树
参考资料
王道数据结构
【数据结构】图的遍历(BFS和DFS)相关推荐
- 数据结构 --- 图的遍历 DFS、BFS
什么是DFS.BFS? 一条线走到底,深度优先遍历,每一个顶点只遍历.只打印一次的方式:DFS.BFS 数据结构 --- 图的存储 单纯地把邻接顶点的邻接顶点打印出来,顶点重复遍历,打印多次 从 A→ ...
- 网状结构(图)图的存储(邻接矩阵、邻接表)、图的遍历(深度DFS、广度BFS)、图的最短路径
图 多对多关系 是一种网状数据结构,图是由非空的顶点集合和一个描述顶点之间关系的集合组成 其定义 Graph = (V, E) V={x | x ∈某个数据对象} E = {<u, v> ...
- 数据结构与算法学习⑤(BFS和DFS 贪心算法 二分查找)
数据结构与算法学习⑤ 数据结构与算法学习⑤ 1.BFS和DFS 1.1.深度优先搜索算法 1.2.广度优先搜索算法 面试实战 102. 二叉树的层序遍历 104. 二叉树的最大深度 515. 在每个树 ...
- 【小算法】图的遍历之深度优先(DFS)
谈到算法,图的操作是避免不了. 而我们一般谈到图时,又必定会谈到图的遍历. 图的遍历通常有 2 种,深度优先(DFS) 和广度优先(BFS). 本篇博文讲解深度优先(DFS). 图的表示 图有两种表示 ...
- 数据结构 - 图的遍历
图的遍历 图的遍历(Traversing Graph):从图的某一顶点出发,访遍图中的其余顶点,且每个顶点仅被访问一次. 图的遍历算法是各种图的操作的基础.但图的遍历存在以下特点: ◆ 复杂性:图的任 ...
- 图模板、BFS、DFS的C++实现
图 图的存储方式有两种:邻接矩阵和邻接表. 邻接矩阵 用二维数组来表示顶点之间是否存在边,边的权重为多少.对于无向图来说,邻接矩阵是一个对称矩阵.缺点是邻接矩阵虽然比较好写但是需要开辟一个二维数组,如 ...
- 无向图的遍历-BFS与DFS
一,理论部分 无向图的遍历可用深度搜索(DFS)与广度搜索(BFS) 深度搜索的基本方式是由图的一个节点1出发然后随机选一个与其相邻的节点2,接着在选择一个与其相邻的节点3,当一条路遍历完后再选择最近 ...
- 图的遍历 BFS遍历(深学思维)
前言: 这篇文章还是是为了帮助一些 像我这样的菜鸟 找到简单的题解 问题描述: 马上到寒假了,JXY准备去n大城市游玩.这些城市之间有些有航线,有些没有.由于JXY特别懒,现在他想请一个更蒟蒻的人AY ...
- LeetCode 547. 朋友圈(图的遍历BFS DFS)
文章目录 1. 题目 2. 解题 2.1 BFS 广度优先 2.2 DFS 深度优先 1. 题目 问有几个连通网络 2. 解题 2.1 BFS 广度优先 参考图的数据结构 class Solution ...
- 数据结构-图及其遍历
图-邻接矩阵 #include<iostream> #define MAX_VERTS 20 using namespace std; //邻接矩阵 浪费空间class Vertex { ...
最新文章
- usaco A game
- nohup 和后台运行符号
- 常用的CSS命名规则
- System Center产品相关开发(1)-SCOM和SCVMM简介
- centos c++ 找不到头文件mysql.h
- Introduction to Mathematical Thinking - Week 3
- SDNU 1464.最大最小公倍数(思维)
- 关于“svn: Can't connect to host '*.*.*.*': 由于连接方在一段时间后没有正确答复或连接”的解决方法...
- 【Pascal's Triangle II 】cpp
- HDU 6178 Monkeys
- Windows 游戏之父,DirectX 作者 Eric Engstrom 意外去世,享年55岁
- 源码专题之spring设计模式:策略模式、原型模式、模板模式
- MOSS2007匿名调查列表使用分页符导致的错误分析
- id和instancetype
- android framework手机系统改机相关知识简单方案
- python的sdk是什么意思_python sdk是什么
- 角色与使命:学生干部如何平衡工作与学习的关系?
- CAN总线(一)——CAN总线是什么,在哪用,怎么用?
- 盘盈的存货一般应作为什么处理
- 最没灵魂的爬虫——Selenium 游戏信息的爬取与分析
热门文章
- Spring 事务core 模块-JdbcTeamplate 对象
- Spring 核心容器类BeanFactory
- 缓存-SpringCache-整合体验@Cacheable
- 微服务网关-Gateway-LoadBalancerClient实现负载均衡讲解
- RequestBody注解
- SpringBoot高级-检索-Elasticsearch简介安装
- 单列设计模式 懒汉式及多线程debug
- android 自定义 child,Android自定义View
- oracle xdb插件报错,注册XML Schema到ORACLE XDB并对XML进行验证
- 我犯的错误--关于主键