首页 > 其他分享 >图的广度优先遍历BFS得到各节点的度

图的广度优先遍历BFS得到各节点的度

时间:2024-03-31 10:33:55浏览次数:21  
标签:10 结点 遍历 队列 ++ BFS int values 节点

难题

初始化,在下面的代码中,我们创建了一个具有十个结点的图结构,并且通过rand函数来给各结点之间的路径赋值。

typedef struct Graph {          //创建图结构
	int values[10][10];         //图结构的邻接矩阵,权值为0意味两结点无路径
} Graph;

void FillGraph(Graph &g) {      //初始化出一个随机权值的图结构
	srand((unsigned int)time(NULL));   //声明时间种子
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			if (i != j) {              //判断是否同个结点
				g.values[i][j] = rand() % 2;    //权值取0~1的随机数
				g.values[j][i] = g.values[i][j];//对称赋值
			} else 
				g.values[i][j] = 0;    //同个结点到同个结点之间权值为0
		}
	}
}

//展示图结构中各结点之间的权值 
void ShowValues(Graph g) {
	cout << "Values of each node:" << endl; 
	for(int i = 0; i < 10; i++) {
		cout<< i << ": ";
		for(int j = 0; j < 10; j++) {
			cout << g.values[i][j] << " ";
		}
		cout << endl;
	}
	cout<<endl;
} 

请添加图片描述

暴力遍历

倘若通过暴力遍历,显然也是能得到各结点的度的,但从时间复杂度和空间复杂度来讲并不完美。

  • 时间复杂度:O(V2),其中*V*是节点的数量。由于使用了两层循环来遍历所有节点,时间复杂度为*O*(*V*2)。
  • 空间复杂度:O(V),需要一个大小为V的数组来记录每个节点的度数。
//暴力遍历得到图中各结点的度 
void PowerDegree(const Graph g) { 
	vector<int> degree(10, 0);             //记录各结点度的数组,初始化为0 
	for (int i = 0; i < 10; i++) {         //通过二层循环来得到各结点之间的度 
		for (int j = 0; j < 10; j++) {
			if (g.values[i][j] != 0) {
				degree[i]++;
			}
		}
	}
	cout << "Power to Degrees of each node:" << endl;               //输出暴力遍历得到的结果 
	for (int i = 0; i < 10; i++) {
		cout << "Node " << i << ": " << degree[i] << endl;
	}
	cout << endl;
}

接下来,我们需要了解一下有关图的广度优先遍历和深度优先遍历。

广度优先遍历BFS

广度优先遍历是一种由近及远的遍历方式,从某个节点出发,始终优先访问距离最近的顶点,并一层层向外扩张

BFS 通常借助队列来实现,代码如下所示。队列具有“先入先出”的性质,这与 BFS 的“由近及远”的思想异曲同工。

实现步骤:
  1. 将起始节点放入队列。
  2. 从队列中取出第一个节点,访问它,并将它的所有未访问的邻居节点加入队列。
  3. 重复步骤2,直到队列为空。

时间复杂度:O(V+E),V为节点数,E为边数。空间复杂度:O(V),因为最多同时存储V个节点

在这里插入图片描述

如上图,

1.1将结点0放入队列 队列(0)

1.2结点0取出并访问,将结点1和结点3放入队列 队列(1,3)

2.2 取出结点1并访问,将结点2和结点4放入队列 队列(3,2,4)

3.2 取出结点3并访问,将结点6放入队列 队列(2,4,6)

关键

  1. 重复放入队列的问题?

    在这里有个重复结点4,即结点1相邻结点4,通过结点1放入结点4之后,访问结点3时不必再放入。

    因此需要来记录当前结点有没有被访问过,因为本文使用的是C语言,所以直接用一个长度跟结点数一样的布尔数组来记录,倘若C++与Java可以使用哈希表来记录更便捷。

  2. 算法实现时,怎么将一个结点相邻的多个结点放入队列呢?

    通过一层循环判断是否有权值+是否已访问,得到当前节点是否可以放入队列。

代码


//广度优先遍历来得到图中各结点的度 
void BFSDegree(Graph g) {
	vector<int> degree(10, 0);        //记录各结点度的数组,且初始化为0
	vector<bool> isvisit(10, false);        //记录当前结点是否被访问,且初始化为false
	queue<int> q;                     //声明BFS需要的队列 
	q.push(0);                        //将结点0放入队列中 
	
	while (!q.empty()) {              //队列不为空是循环条件 
		int index = q.front();        //访问(得到)队首元素 
		q.pop();                      //取出队首元素 
		isvisit[index] = true;        //意味已访问 
		
		for(int j = 0; j < 10; j++) {    //循环得到度 
			if(j == index) continue;     //如果是本身结点,就跳过本次循环 
			if(g.values[index][j]) degree[index]++;      //有路径,访问结点度数加一 
			if(!isvisit[j]){                             //当未访问时,可放入队列 
				q.push(j);
				isvisit[j] = true;
			}
		} 
	}
	cout <<"BFS to Degrees of each node:" << endl;      //输出广度优先搜索得到的结果
	for (int i = 0; i < 10; i++) {
		cout << "Node " << i << ": " << degree[i] << endl;
	}
	cout << endl;
}

请添加图片描述

总代码

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <time.h>

using namespace std;

typedef struct Graph {          //创建图结构
	int values[10][10];         //图结构的邻接矩阵,权值为0意味两结点无路径
} Graph;

void FillGraph(Graph &g) {      //初始化出一个随机权值的图结构
	srand((unsigned int)time(NULL));   //声明时间种子
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			if (i != j) {              //判断是否同个结点
				g.values[i][j] = rand() % 2;    //权值取0~1的随机数
				g.values[j][i] = g.values[i][j];//对称赋值
			} else 
				g.values[i][j] = 0;    //同个结点到同个结点之间权值为0
		}
	}
}

//展示图结构中各结点之间的权值 
void ShowValues(Graph g) {
	cout << "Values of each node:" << endl; 
	for(int i = 0; i < 10; i++) {
		cout<< i << ": ";
		for(int j = 0; j < 10; j++) {
			cout << g.values[i][j] << " ";
		}
		cout << endl;
	}
	cout<<endl;
} 

//暴力遍历得到图中各结点的度 
void PowerDegree(const Graph g) { 
	vector<int> degree(10, 0);             //记录各结点度的数组,初始化为0 
	for (int i = 0; i < 10; i++) {         //通过二层循环来得到各结点之间的度 
		for (int j = 0; j < 10; j++) {
			if (g.values[i][j] != 0) {
				degree[i]++;
			}
		}
	}
	cout << "Power to Degrees of each node:" << endl;               //输出暴力遍历得到的结果 
	for (int i = 0; i < 10; i++) {
		cout << "Node " << i << ": " << degree[i] << endl;
	}
	cout << endl;
}


//广度优先遍历来得到图中各结点的度 
void BFSDegree(Graph g) {
	vector<int> degree(10, 0);        //记录各结点度的数组,且初始化为0
	vector<bool> isvisit(10, false);        //记录当前结点是否被访问,且初始化为false
	queue<int> q;                     //声明BFS需要的队列 
	q.push(0);                        //将结点0放入队列中 
	
	while (!q.empty()) {              //队列不为空是循环条件 
		int index = q.front();        //访问(得到)队首元素 
		q.pop();                      //取出队首元素 
		isvisit[index] = true;        //意味已访问 
		
		for(int j = 0; j < 10; j++) {    //循环得到度 
			if(j == index) continue;     //如果是本身结点,就跳过本次循环 
			if(g.values[index][j]) degree[index]++;      //有路径,访问结点度数加一 
			if(!isvisit[j]){                             //当未访问时,可放入队列 
				q.push(j);
				isvisit[j] = true;
			}
		} 
	}
	cout <<"BFS to Degrees of each node:" << endl;      //输出广度优先搜索得到的结果
	for (int i = 0; i < 10; i++) {
		cout << "Node " << i << ": " << degree[i] << endl;
	}
	cout << endl;
}

int main() {
	Graph g;
	FillGraph(g);
	ShowValues(g); 
	PowerDegree(g);
	BFSDegree(g);
	return 0;
}

运行结果

请添加图片描述
请添加图片描述
请添加图片描述

标签:10,结点,遍历,队列,++,BFS,int,values,节点
From: https://blog.csdn.net/weixin_72939806/article/details/137193857

相关文章

  • maya给模型以及子节点随机染色
    maya给模型以及子节点随机染色 importrandomimportmaya.cmdsaspydefmaterial1():sel=py.ls(sl=True)ifsel!=[]:forobjinsel:myShade=py.shadingNode('lambert',asShader=True)#printmyShademyShad......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-5 同步异步删除zk节点
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12721 1重点关注1.1本节内容javaapi客户端删除节点,包含同步修改和异步修改,只做了异步,同步不通用(因为没有回调函数,不知道是否删除成功)也可以参照视频看下 1.2javaapi删除节点......
  • L2-006 树的遍历
    先建树,然后遍历数组。这种方式比较消耗空间,适用于数据量小的情况,如果形成一条链,那将是致命的这个空间。#include<bits/stdc++.h>usingnamespacestd;constintN=1e5+10;intin[N],post[N];vector<int>tree(N,-1);voidbuild(introot,intstart,inted,intidx)......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-4 修改zk节点数据
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12720 1重点关注1.1本节内容javaapi客户端修改节点,只做了同步修改,异步修改方式如1.3,可以参考6-3异步新增 1.2javaapi修改节点同步修改/***参数:......
  • 取二维多段线或三维多段线的所有节点
    ;取得3dpolyline的所有节点,因3dpolyline节点信息不信在子图元中,而entget函数只能获取POLYLINE主图元数据;因此要使用entnext函数依次获取所有VERTEX图元的数据,直到遇到SEQEND图元为止(defunc:g-polyline-vertex() (setqentname(car(entsel"\n请选取二维多段线或三维多......
  • 探索分布式人工智能:多节点合作引领智能革命
    引言:随着人工智能(AI)技术的不断发展,分布式人工智能作为一种新兴的技术模式正逐渐崭露头角。它通过多个节点之间的协作与通信,将数据和计算资源分散在多个地方,从而实现更加灵活、高效的智能计算。本文将深入探讨分布式人工智能的概念、技术原理以及在各个领域的应用,展望其在智能革命......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-3 同步异步创建zk节点
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12719 1重点关注1.1本节内容javaapi客户端新增临时节点和永久节点 1.2javaapi新增节点同步调用/***同步或者异步创建节点,都不支持子节点的递归......
  • Acwing 5475. 聚会 ( BFS )
    https://www.acwing.com/problem/content/5478/输入样例1:5543124321223344145输出样例1:22223输入样例2:76321233221122334255667输出样例2:1112211#pragmaGCCdiagnosticerror"-std=c++11"#pragmaGCCtarget(......
  • skynet非单点类型节点的管理(一):玩家代理节点
    单个skynet进程,或者说单台机器的承载业务能力是有上限的,对于负责玩家主要业务的节点,横向扩展以提高游戏承载能力是必须的。对于滚服架构,玩家角色与指定业务节点(单服)固定对应,连接游戏业务前通过中央后台获取到指定信息进行连接。承载能力通过新增单服完成,这里我们只对世界服架构做......
  • 搜索与图论(二)bfs---以题为例
    给定一个 n×m的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中 0 表示可以走的路,1 表示不可通过的墙壁。最初,有一个人位于左上角 (1,1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。请问,该人从左上角移动至右下角 (n,m)处,至少需要移动多......