图的遍历——BFS与DFS

图的遍历是指对图中的顶点按照一定的顺序进行访问。
图的遍历一般分为两种:DFS与BFS~

一、深度优先搜索

每次都是走到不能再走了才回到最近的一个交叉口。
***连通分量:***无向图中,如果两个顶点之间可以相互到达,(可以是通过一定的路径间接到达),那么这两个顶点就称为强连通。如果图G(V,E)的任意两个顶点都连通,则称图G为连通图;否则就是非连通图,并且称其中的极大连通子图为连通分量。
***强连通分量:***有向图中,如果两个顶点可以各自通过一条有向路径到达另一个顶点,就称为这两个顶点为强连通。如果图G(V,E)的任意两个顶点都强连通,就称图G为强连通图;否则就是非强连通图,且称其中的极大强连通子图为强连通分量。

下面的代码是DFS的伪代码~(邻接表和邻接矩阵都能套)

DFS(u){		//访问顶点u
	vis[u] = true;		//将u设置为已经访问
	for(从u出发能到达的所有顶点)	//枚举从u出发能到达的所有顶点
		if vis[v] == false		//如果v没有被访问
			DFS(v);
}

DFSTrave(G){
	for(G中的所有顶点u)
		if vis[u] == false
			DFS(u);
}

设置全局变量:

const int MAXV = 1000;		//最大顶点数
const int INF = 1000000000;		//设INF是一个很大的数

邻接矩阵模版

int n, G[MAXV][MAXV];	//n为顶点数
bool vis[MAXV] = {false};	//如果顶点i被访问,那么vis[i] = true

void DFS(int u, int depth){
	vis[u] = true;
	for(int v = 0; v < n; v ++){
		if(G[u][v] != INF && vis[v] == false)
			DFS(v, depth + 1);
	}
}

void DFSTrave(){
	for(int u = 0; u < n; u++){
		if(vis[u] == false)
			DFS(u, 1);
	}
}

邻接表模版

vector<int> Adj[MAXV];
int n;
bool vis[MAXV] = {false};

void DFS(int u, int depth){
	vis[u] = true;
	for(int i = 0; i < n; i++){
		int v = Adj[u][i];
		if(vis[v] == false)
			DFS(v, depth + 1);
	}
}

void DFSTrave(){
	for(int v = 0; v < n; v++){
		if(vis[v] == false)
			DFS(v, 1);
	}
}

二、广度优先搜索

基本思想:建立一个队列,并且把初始顶点加入队列,此后每次都取出队首顶点进行访问,并且把该顶点出发可以达到的未曾加入过队列(而不是未访问)的顶点全部加入队列,直到队列为空。

以下为BFS伪代码~

BFS(u){		//遍历u所在的模块
	queue q;
	inq[u] = true;		//设置u已经被加入过队列
	while(q非空){
		取出q的队首元素u进行访问;
		for(从u出发可达的所有顶点v)
			if(inq[v] == false){
				将v入队;
				inq[v] = true;
			}
	}
}

BFSTrave(G){
	for(G的所有结点u)
		if(inq[u] == false)
			BFS(u);
}

邻接矩阵模版

int n, G[MAXV][MAXV];
bool inq[MAXV] = {false};

void BFS(int u){
	queue<int> q;
	q.push(u);
	inq[u] = true;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int v = 0; v < n; v++){
			//如果u的邻接点v未曾加入过队列
			if(inq[v] == false && G[u][v] != INF){
				q.push(v);
				inq[v] = true;
			}
		}
	}
}

void BFSTrave(){
	for(int u = 0; u < n; u++){
		if(inq[u] == false)
			BFS(q);
	}
}

邻接表模版

vector<int> Adj[MAXV];
int n;
bool inq[MAXV] = {false};

void BFS(int u){
	queue<int> q;
	q.push(u);
	inq[u] = true;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int i = 0; i < n; i++){
			int v = Adj[u][i];
			if(inq[v] == false){
				q.push(v);
				inq[v] = true;
			}
		}
	}
}

void BFSTrave(){
	for(int u = 0; u < n; u++){
		if(inq[u] == false)
			BFS(q);
	}
}

与树的BFS类似,在给定BFS初始点的情况下,可能需要输出该连通块内所有其他顶点的层号,这时只需要修改少量内容即可达到要求(以邻接表为例,邻接矩阵也是同样的道理)

struct Node{
	int v;
	int layer;
};

vector<Node> Adj[N];

void BFS(int s){	//s是起始编号
	queue<Node> q;
	Node start;
	start.layer = 0;
	start.v = s;
	q.push(start);
	inq[start.v] = true;
	while(!q.empty()){
		Node topNode = q.front();
		q.pop();
		int u = topNode.v;
		for(int i = 0; i < Adj[u].size(); i++){
			Node next = Adj[u][i];
			next.layer = topNode.layer + 1;
			if(inq[next.v] == false){
				q.push(next);
				inq[next.v] = true;
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾尔伯特想变瘦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值