【知识点1】图的存储、图的BFS、DFS遍历⭐⭐⭐⭐⭐

一定要考虑到非连通图的情况。已经在这里栽了好多跟头了!!!


今天也是为了cc,努力奋斗的一天ヾ(≧▽≦*)o

1. 图的存储

邻接矩阵

  • 适合顶点数 小于1000
  • 适合每两个顶点之间 只有一条边 的情况;
  • 其实相比于邻接表,这个已经很少用到了;

邻接表

  • 适合顶点数 大于1000
  • 非常常用,而且需要结合结构体一起使用
  • 能够用于两个结点之间 存在多条边 的情况

链式前向星

2. 深度优先搜索(DFS)

基本思想

在这里插入图片描述

常量定义

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

注意:两者都需要一个vis数组来保存是否可以访问。以及不可达的判断!

邻接矩阵实现DFS

/*
	邻接矩阵版 
*/
 
int  n,G[MAXV][MAXV];	//n为顶点数,MAXV为最大顶点数
bool vis[MAXV] = {false};	//如果顶点i已经被访问了,则vis[i]==true。初值为false

void DFS(int u,int depth){	//u设置为当前访问的顶点标号,depth为深度 
	vis[u] = true;	//设置u已被访问
	//如果需要对u进行一些操作,可以在这里进行
	//下面对所有从u出发能够到达的分支顶点进行枚举
	for(int v = 0;v < n;v++){	//对每个顶点v 
		if(vis[v] == false && G[u][v] != INF){	//如果v未被访问,且u可到达v 
			DFS(v,depth+1);	//访问v,深度加1 
		} 
	} 
} 

void DFSTrave(){	//遍历图G 
	for(int u = 0; u < n;u++){	//对每个顶点u 
		if(vis[u] == false){	//如果u未被访问 
			DFS(u,1);	//访问u和u所在的连通块,1代表初始为第一层 
		}
	} 
} 

邻接表实现DFS

/*
	邻接表版
*/
vector<int> Adj[MAXV];	//图G的邻接表
int n;	//n为顶点数,MAXV为最大顶点数
bool vis[MAXV] = {false};	//如果顶点i已被访问,则vis[i]==true,初值为false

void DFS(int u,int depth){	//u为当前访问的顶点坐标,depth为深度 
	vis[u] = true;	//设置u已被访问
	//如果需要对u进行一些操作,可以在此处进行
	for(int i=0;i<Adj[u].size();i++){	//对从u出发可以到达的所有顶点v 
		int v = Adj[u][i];
		if(vis[v] == false){	//如果v未被访问  
			DFS(v,depth+1);		//访问v,深度加一 
		}
	} 
} 

void DFSTrave(){	//遍历图G 
	for(int u=0;u<n;u++){	//对每一个顶点u 
		if(vis[u] == false){	//如果u未被访问 
			DFS(u,1);	//访问u和u所在的连通块,1为初始为第一层 
		}
		 
	} 
}

广度优先搜索(BFS)

注意:这里的bool数组是用于标记是否已经加入了队列,而不是是否已经访问了,因为加入队列并不代表会被立即访问,可能还需要再等一下才能访问。

基本思路

BFS(u){		//遍历u所在的连通块 
	queue q;	//定义队列q
	将u入队;
	inq[u] = true;	//设置u已经被加入到队列中
	while(q非空){	//只要队列非空 
		取出q的队首元素u进行访问;
		for(从u出发可以到达的所有顶点v)		//枚举从u能够直接到达的顶点v
			if(inq[v] == false){			//如果v未曾加入过队列 
				将v入队;
				inq[v] = true;				//设置v已被加入到队列 
			} 
	} 
}

BFSTrave(G){	//遍历图G 
	for(G的所有顶点u)	//枚举G的所有顶点u
		if(inq[u] == false){	//如果u未曾加入过队列 
			BFS(u);		//遍历u所在的连通块 
		} 
} 

邻接矩阵实现BFS

int n,G[MAXV][MAXV];	//n为顶点数,MAXV为最大顶点数
bool inq[MAXV] = {false};	//若顶点i未曾如果队列,则inq[i]==true,初值为false

void BFS(int u){	//遍历u所在的连通块 
	queue<int> q;	//定义队列q
	q.push(u);		//将初始点u入队
	inq[u] = true;	//设置u已被加入过队列
	while(!q.empty()){	//只要队列非空 
		int u = q.front();	//取出队首元素
		q.pop();			//将队首元素出队
		for(int v = 0;v<n ;v++){
			if(inq[v] == false && G[u][v] != INF){
				q.push(v);	//将v入队
				inq[v] = true;	//标记v为已被加入队列 
			}
		} 
	} 
} 

void BFSTrave(){	//遍历图G
	 for(int u=0;u<n;u++){	//枚举所有的顶点 
	 	if(inq[u] == false){	//如果u未曾加入过队列 
	 		BFS(q);				//遍历u所在的连通块 
		 }
	 }
} 

邻接表实现BFS

vector<int> Adj[MAXV];	//图G,Adj[u]存放从顶点u出发可以到达的所有顶点
int n;	//n为顶点数,MAXV为最大的顶点数
bool inq[MAXV] = {false};	//若顶点i曾入队列,则inq[i]==true。初值为false

void BFS(int u){	//遍历单个连通块 
	queue<int> q;	//定义队列q
	q.push(u);		//将初始点u入队
	inq[u] = true;	//设置u已被加入过队列
	whiel(!q.empty()){	//只要队列非空 
		int u = q.front();	//取出队首元素
		q.pop();			//将队首元素出队
		for(int i=0;i<Adj[u].size();i++){	//枚举从u出发能够到达的所有顶点 
			int v = Adj[u][i];
			if(inq[v] == false){	//如果v未曾加入过队列
				q.push(v);	//将v入队
				inq[v] = true;	//标记v为已被加入过队列 
			} 
		} 
	} 
} 


void BFSTrave(){	//遍历图G 
	for(int u=0;u<n;u++){	//枚举所有的顶点 
		if(inq[u] == false){	//如果u未曾加入过队列 
			BFS(q);			//遍历u所在的连通块 
		} 
	} 
} 

参考文档

算法笔记

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值