数据结构 第六章 图 (广度优先BFS;深度优先DFS;有向图;无向图)

数据结构 第六章 图

概述

邻接关系:顶点和顶点间的关系
关联关系:顶点和边的关系
邻接矩阵:n个顶点,则为n×n,元素为1表示顶点间有关联
关联矩阵:n行表示n个顶点,e列表示e条边
在这里插入图片描述
枚举点的所有邻居
在这里插入图片描述

广度优先搜索

在这里插入图片描述
在这里插入图片描述
将图划分为若干种等价类(图中的环路圈),同一等价类内各顶点的边不会被采纳,连接相邻等价类顶点的边会被采纳,但是不一定会被采纳。这样能是的图划分为极大无环图,则转换为一棵树,称为支撑树,即BFS树,广度优先搜索等价于树的层次遍历,结点到根结点的最短通路为BFS树中的通路
每个顶点状态变化:UNDISCOVERED–>DISCOVERED–>VISITED
算法过程:栈实现
1.访问结点A,并将A和A的邻点状态由UNDISCOVERED改为DISCOVERED,并全部入栈
2.按一定顺序或者随机访问A的邻点B,并将A和B之间的边纳入BFS Tree。将该邻点B的状态由DISCOVERED改为VISITED,并将B的所有UNDISCOVERED的邻点入栈并该状态为DISCOVERED。
3.访问A的第二个邻点C,如此往复…以生成BFS Tree

template<typename Tv,typename Te>
void Graph<Tv,Te>::BFS(int v,int clock){
Queue<int> Q;status(v)=DISCOVERED;Q.enqueue(v);
while(!Q.empty()){
	int v= Q.dequeue();
	dTime(v)=++clock;
	for(int u=firstNbr(v),-1<u;u=nextNbr(v,u))//遍历v的所有邻点
	{	if(status(u)=UNDISCOVERED){//若v的邻点u尚未被发现,则
		status(u)=DISCOVERED;Q.enqueue(u);//发现并将结点入队,访问结点
		status(v,u)=TREE;parent(u)=v;//引入树边从而构造BFS Tree
		}
		else{
		status(v,u)=CROSS;//否则u和v之间的边归入跨边,不计入BFS Tree
		}
	}
	status(v)= VISITED;
  }
}

复杂度为O(n+e),e为边的个数
总结:(按照字母顺序)访问邻结点并入栈,访问同时将邻结点的邻结点入栈,再按照栈的顺序访问
在这里插入图片描述

深度优先搜索

template<typename Tv,typename Te>
void Graph<Tv,Te>::DFS(int v,int clock){
	dTime(v)=++clock;
	status(v)=DISCOVERED;
	for(int u=firstNbr(v),-1<u;u=nextNbr(v,u))//遍历v的所有邻点
	{	switch(status(u)){
        case UNDISCOVERED:
        	status(v,u)=TREE;parent(u)=v;DFS(u,clock);break;
        case DISCOVERED:
        	status(v,u)=BACKWORD;break;
        default:
        	status(v,u)=dTime(v)<dTime(u)?FORWORD:CROSS;break;
		}

	}
	status v= VISITED;
}

采用迭代的方式实现:
(1)首先选定一个未被访问过的顶点V作为起始顶点(或者访问指定的起始顶点V),并将其标记为已访问过;
(2)然后搜索与顶点V邻接的所有顶点,判断这些顶点是否被访问过,如果有未被访问过的顶点,则任选一个顶点W进行访问;再选取与顶点W邻接的未被访问过的任一个顶点并进行访问,依次重复进行。当一个顶点的所有的邻接顶点都被访问过时,则依次回退到最近被访问的顶点。若该顶点还有其他邻接顶点未被访问,则从这些未被访问的顶点中取出一个并重复上述过程,直到与起始顶点V相通的所有顶点都被访问过为止。
(3)若此时图中依然有顶点未被访问,则再选取其中一个顶点作为起始顶点并访问之,转(2)。反之,则遍历结束。
总结:
无向图:(按照字母顺序)访问邻结点,如果邻结点无未访问的邻接点则回溯
有向图:优先访问出的邻点,当访问完所有可达域后若还未访问完整个图,则再枚举其他顶点,具体实现方法是对DFS作封装,对未发现的结点再进行DFS算法

在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值