《算法笔记》学习记录 Part 4 图(上)

第十章    数据结构专题 —— 图(上)

10.1 图的存储

10.1.1 邻接矩阵

设图G(V,E)的顶点标号为0,1,……,N-1,那么可以令二维数组G[N][N]的二维分别表示图的顶点标号,即如果G[i][j] = 1,则说明顶点i和顶尖j之间不存在边,而这个二维数组G[][]则被称为邻接矩阵,如果存在边权,令G[i][j]存放边权,对不存在的边可以设边权为0、-1、INF

10.1.2 邻接表

设图G(V,E)的顶点标号为0,1,……,N-1,每个顶点都有可能有若干条出边,如果把同一个顶点的所有出边放在一个列表,那么N个顶点就会有N个列表(没有出边,对应空表)。这N个列表被称为图G的邻接表,记为Adj[N]

由于vector有变长数组之称,因此可以开一个vector数组Adj[N],其中N为顶点个数。这样每个Adj[i]就是一个变长数组vector,使得存储空间与图的边数有关。

如果邻接表只存放每条边的终点编号,而不存放边权,则vector中的元素类型可以直接定义为int型

vector<int> Adj[N];

如果想添加一条从1号顶点到3号顶点的有向边

Adj[1].push_back(3);

如果要同时存放边的终点和边号,可以建立结构体Node

struct Node{
	int v;	//边的终点编号
	int w;	//边权
};

vector<Node> Adj[N];

如果想要添加从1号到3号顶点的有向边,边权为4

Node temp;
	temp.v=3;
	temp.w=4;
	Adj[1].push_back(temp);

更快的做法是定义结构体Node函数

struct Node{
	int v;	//边的终点编号
	int w;	//边权
	Node(int _v,int _w):v(_v),w(_w){}
};
//	如果想要添加从1号到3号顶点的有向边,边权为4
	Adj[1].push_back(Node(3,4));

10.2 深度优先搜索遍历(DFS)

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

void DFS(int u,int depth){	//u为当前访问的顶点标号,depth为深度
	vis[u]=true;
	//如果需要对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);			
		}
	}
}
//DFS 邻接表
vector<int> Adj[MAXV];
int n;					//n为顶点数
bool vis[MAXV] = {false};//如果顶点i已经被访问,则vis[i]==false。初值为false

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

10.3 广度优先搜索(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.push(u);
	inq[u] = true;	//设置u已被加入队列
	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);	//将v入队
				inq[v] = true;
			}
		}
	}
}

void BFSTrave(){
	for(int u=0;u<n;u++){
		if(inq[u]==false){
			BFS(u);
		}
	}
}
//邻接表版
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<Adj[u].size();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(u);
		}
	}
}











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猪突猛进!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值