数据结构与算法:图的BFS及性能分析

一. 图的广度优先遍历

图的广度优先遍历可以联系二叉树的层序遍历,其基本思想是:首先,访问起始节点v,之后,访问与起始节点v相连的各个未被访问过的节点w1,w2,...,wi,之后,再对这些节点,进行上面的操作。

在分析其算法的时间和空间开销之前,我们必须知道算法的实现流程:

广度优先遍历是一种分层查找的过程,与深度优先遍历的不同之处在于,它不需要有退回的情况,因此,它不是一个递归的算法。但是,为了实现逐层的访问,我们必须借助辅助队列来实现

void BFS(Graph G,int v){//从顶点v出发,广度优先遍历图G
	visit(v);
	visited[v] = true;
	EnQueue(Q,v);
	while(!isEmpty(Q)){
		DeQueue(Q,v);
		for(w = FirstNeighbor(G,v);w>=0;w = NextNeighbor(G,v,w)){//不断找到与v节点相邻的节点
			if(!visited[w]){
				visit(w);
				visited[w] = true;
				EnQueue(Q,w);
			}
		}
	}

void BFSTraverse(Graph G){
	for(int i = 0;i<G.vexnum;i++){//初始化visit数组
		visited[i] = false;
	}
	InitQueue(Q);
	for(int i = 0;i<G.vexnum;i++){
		if(!visited[i]){
		BFS(G,i);
		}
	}
}

二. 图的常见存储模式

常见的图的存储方式有邻接矩阵存储和邻接表存储,邻接矩阵是用一维数组存储节点信息,用二维数组存储边的信息,时间复杂度为O(V2),而邻接表是采用顺序存储图的节点信息(顶点表),链式存储图的边的信息(边表),对于无向图的情况,由于一条边会增加节点的两个度,因此邻接表存储无向图的情况,边节点的个数为边数的两倍,即2E,加之有V个节点,因此邻接表存储的空间开销是O(V+2E)

三. 基于邻接矩阵和邻接表的查找

1. FirstNeighbor(G,v):查找节点v的第一个邻接点,对于无向图和有向图是相同的情况。第一,如果图是采取邻接矩阵的存储模式,那么最好的情况,就是遍历序列的第一个元素就符合情况,因此,最好情况下的时间复杂度为O(1),最坏的情况则是要遍历整个图的节点,此时的时间复杂度为O(n),而对于邻接表的存储,因为边节点直接体现了节点相连的节点,因此,通过邻接表查找第一个邻接点的时间开销为O(1)(对于有向图仅是查找出边的情况)

2. NextNeighbor(G,v,w):假设节点w是v的第一个邻接点,该函数返回除了w以外,与v相连的下一个邻接点,其时间和空间开销同上

四. BFS的复杂度分析:

1. 时间复杂度:

首先,我们需要确定BFS遍历的时间开销来源是什么,这是最重要的,BFS遍历的时间开销有二:访问节点+探索边。访问节点需要遍历整个图,因此时间复杂度为O(V),而遍历边,需要在二维数组中查看每一个节点与其相连的边。因此对于邻接矩阵存储模式,总的时间开销为O(V+V2),保留最大项,为O(V2),而对于邻接矩阵存储,遍历节点的时间复杂度为O(V),遍历边则直接遍历边节点即可,因此遍历边的时间复杂度为O(E),故总的时间复杂度为O(V+E)

2. 空间复杂度:

使用了辅助队列,n个节点均需要入队一次,故空间复杂度为O(V)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值