数据结构学习:图的基本操作

数据结构学习:图的基本操作
图的基本操作:

	• Adjacent(G,x,y):判断图G是否存在边<x, y>或(x, y)。
	
	• Neighbors(G,x):列出图G中与结点x邻接的边。
	
	• InsertVertex(G,x):在图G中插入顶点x。
	
	• DeleteVertex(G,x):从图G中删除顶点x。
	
	• AddEdge(G,x,y):若无向边(x, y)或有向边<x, y>不存在,则向图G中添加该边。
	
	• RemoveEdge(G,x,y):若无向边(x, y)或有向边<x, y>存在,则从图G中删除该边。
	
	• FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1。
	
	• NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1。
	
	• Get_edge_value(G,x,y):获取图G中边(x, y)或<x, y>对应的权值。
	
	• Set_edge_value(G,x,y,v):设置图G中边(x, y)或<x, y>对应的权值为v。
广度优先遍历
bool visited[Max_Vertex_Num];//访问标记数组。初始值都为false

void BFS(Grapg G,int v)		//从顶点V开始广度优先遍历图G
{
	visit(v);				//访问顶点v
	visited[v] = True;		//标记顶点v为True,记为已访问
	EnQuene(Q,v);			//将顶点v入队
	while(!isEmpty(Q))		
	{//当队列Q不为空时
		DeQuene(Q,v);		//队头顶点出队,并返回值为v
		for(w = firstNeighbor(G,v); w >= 0;w = NextNeighbor(G,v,w))
		{//定义w为v在图G中的第一个临界点
		//每循环一次,w为除w之外顶点v的下一个邻接点的顶点号,若w是v的最后一个邻接点,则返回-1
			if(!visited[w])//当w为False,即未访问过时
			{
				visit(w);	//访问w顶点
				visited[w] = True;//标记w顶点为已访问
				EnQuene(Q,w);//将w顶点入队
			}
		}
	}
}

同⼀个图的邻接矩阵表示⽅式唯⼀,因此⼴度优先遍历序列唯⼀
同⼀个图邻接表表示⽅式不唯⼀,因此⼴度优先遍历序列不唯⼀
该广度优先遍历存在问题:当图是非联通图的话,无法遍历完所有结点
需要对该算法进行优化

改进后
将所有顶点存入数组,然后对其进行广度优先遍历

void BFSTravares(Grapg G)
{
	for(int i = 0;i < G.vexnum;++i)
	{
		visited[i] = False;		//初始化标记数组
	}
	InitQuene(Q);			//初始化队列Q
	for(i = 0;i < G.vexnum;++i)//从0号顶点开始遍历
	{
		if(!visited[i])		//若该顶点为访问过,则去访问该顶点以及其所连通的顶点
			BFS(G,i);
	}
}
// 广度优先遍历
bool visited[Max_Vertex_Num];//访问标记数组。初始值都为false

void BFS(Grapg G,int v)		//从顶点V开始广度优先遍历图G
{
	visit(v);				//访问顶点v
	visited[v] = True;		//标记顶点v为True,记为已访问
	EnQuene(Q,v);			//将顶点v入队
	while(!isEmpty(Q))		
	{//当队列Q不为空时
		DeQuene(Q,v);		//队头顶点出队,并返回值为v
		for(w = firstNeighbor(G,v); w >= 0;w = NextNeighbor(G,v,w))
		{//定义w为v在图G中的第一个临界点
		//每循环一次,w为除w之外顶点v的下一个邻接点的顶点号,若w是v的最后一个邻接点,则返回-1
			if(!visited[w])//当w为False,即未访问过时
			{
				visit(w);	//访问w顶点
				visited[w] = True;//标记w顶点为已访问
				EnQuene(Q,w);//将w顶点入队
			}
		}
	}
}

复杂度分析:
空间复杂度:最坏情况,辅助队列⼤⼩为 O(|V|)

邻接矩阵存储的图:
访问 |V| 个顶点需要O(|V|)的时间
查找每个顶点的邻接点都需要O(|V|)的时间,⽽总共有|V|个顶点
时间复杂度= O(|V|^2 )
邻接表存储的图:
访问 |V| 个顶点需要O(|V|)的时间
查找各个顶点的邻接点共需要O(|E|)的时间,
时间复杂度= O(|V|+|E|)

⼴度优先⽣成树由⼴度优先遍历过程确定。由于邻接表的表示⽅式不唯⼀,因此基于邻接表的⼴度优先⽣成树也不唯⼀。

对⾮连通图的⼴度优先遍历,可得到⼴度优先⽣成森林

图的深度优先遍历
图的深度优先遍历类似于树的先根遍历

// 宽度优先遍历,使用递归的方法,将一条路径上的结点全部遍历
void DFS(Grapg G,int v)
{
	visit(v);
	visited[v] = True;
	for(w = FirstNeighbor(G,v);w>=0;w = NextNeighbor(G,v,w))
	{
		if(!visited[w])
			DFS(G,w);
	}
}
//为防止图不是连通图,将所有结点存储并依次遍历
void DFSTravares(Grapg G)
{
	for(int i = 0;i < G.vexnum;++i)
	{
		visited[i] = False;		//初始化标记数组
	}
	for(i = 0;i < G.vexnum;++i)//从0号顶点开始遍历
	{
		if(!visited[i])		//若该顶点为访问过,则去访问该顶点以及其所连通的顶点
			DFS(G,i);
	}
}

空间复杂度:来⾃递归函数调⽤栈,最坏情况,递归深度为O(|V|)

时间复杂度=访问各结点所需时间+探索各条边所需时间
邻接矩阵存储的图:
访问 |V| 个顶点需要O(|V|)的时间
查找每个顶点的邻接点都需要O(|V|)的时间,⽽总共有|V|个顶点
时间复杂度= O(|V|^2 )
邻接表存储的图:
访问 |V| 个顶点需要O(|V|)的时间
查找各个顶点的邻接点共需要O(|E|)的时间,
时间复杂度= O(|V|+|E|)

同⼀个图的邻接矩阵表示⽅式唯⼀,因此深度优先遍历序列唯⼀
同⼀个图邻接表表示⽅式不唯⼀,因此深度优先遍历序列不唯⼀

同⼀个图的邻接矩阵表示⽅式唯⼀,因此深度优先遍历序列唯⼀,深度优先⽣成树也唯⼀
同⼀个图邻接表表示⽅式不唯⼀,因此深度优先遍历序列不唯⼀,深度优先⽣成树也不唯⼀

对⽆向图进⾏BFS/DFS遍历
调⽤BFS/DFS函数的次数=连通分量数
对于连通图,只需调⽤1次 BFS/DFS

对有向图进⾏BFS/DFS遍历
调⽤BFS/DFS函数的次数要具体问题具体分析
若起始顶点到其他各顶点都有路径,则只需调⽤1次BFS/DFS 函数
对于强连通图,从任⼀结点出发都只需调⽤1次 BFS/DFS

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小二康

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

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

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

打赏作者

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

抵扣说明:

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

余额充值