DS高阶:图论基础知识

news2025/1/4 20:20:30

一、图的基本概念及相关名词解释

1.1 图的基本概念

        图是比线性表和树更为复杂且抽象的结,和以往所学结构不同的是图是一种表示型的结构,也就是说他更关注的是元素与元素之间的关系。下面进入正题。

       图是由顶点集合及顶点间的关系组成的一种数据结构:G(Graph) = (V, E),其中:

(1)顶点集合V(Vertex) = {x|x属于某个数据对象集}是有穷非空集合;

(2)E(Edge) = {(x,y)|x,y属于V}或者E = {<x, y>|x,y属于V && Path(x, y)}是顶点间关系的有穷集合,也叫做边的集合。其中 (x, y)表示x到y的一条双向通路,即(x, y)是无方向的;Path(x, y)表示从x到y的一条单向通路,即Path(x, y)是有方向的。(也就是说图分为有向和无向)

   下面我们通过一些图来了解一些相关的名词

       在介绍相关名词之前,大家有没有发现G2和我们的二叉树是一样的?那么图和二叉树究竟有什么关系呢??

       其实本质上来说,树是一种特殊的无环连通图,图不一定是树。另一方面,树关注的是节点中存的值,而图关注的是顶点和边的权值(边附带的数据信息)

1.2 图的相关名词解释

顶点和边:图中结点称为顶点,第i个顶点记作vi。两个顶点vi和vj相关联称作顶点vi和顶点vj之间有一条边,图中的第k条边记作ek,ek = (vi,vj)或<vi,vj>

有向图和无向图(边是否有方向):在有向图中,顶点对<x, y>是有序的,顶点对<x,y>称为顶点x到顶点y的一条边(弧),<x, y>和<y, x>是两条不同的边,比如上图G3和G4为有向图。在无向图中,顶点对(x, y)是无序的,顶点对(x,y)称为顶点x和顶点y相关联的一条边,这条边没有特定方向,(x, y)和(y,x)是同一条边,比如上图G1和G2为无向图。注意:无向边(x, y)等于有向边<x, y>和<y, x>

完全图(即每一个顶点都和其他顶点有边):在有n个顶点的无向图中,若有n * (n-1)/2条边,即任意两个顶点之间有且仅有一条边,则称此图为无向完全图,比如上图G1;在n个顶点的有向图中,若有n * (n-1)条边,即任意两个顶点之间有且仅有方向相反的边,则称此图为有向完全图,比如上图G4。

邻接顶点(通过边关联起来的两个点):在无向图中G中,若(u, v)是E(G)中的一条边,则称u和v互为邻接顶点,并称边(u,v)依附于顶点u和v;在有向图G中,若<u, v>是E(G)中的一条边,则称顶点u邻接到v,顶点v邻接自顶点u,并称边<u, v>与顶点u和顶点v相关联。

顶点的度(有几条边就有多少度):顶点v的度是指与它相关联的边的条数,记作deg(v)。在有向图中,顶点的度等于该顶点的入度与出度之和,其中顶点v的入度是以v为终点的有向边的条数,记作indev(v);顶点v的出度是以v为起始点的有向边的条数,记作outdev(v)。因此:dev(v) = indev(v) + outdev(v)。注意:对于无向图,顶点的度等于该顶点的入度和出度,即dev(v) = indev(v) = outdev(v)。

路径:在图G = (V, E)中,若从顶点vi出发有一组边使其可到达顶点vj,则称顶点vi到顶点vj的顶
点序列为从顶点vi到顶点vj的路径。 

路径长度:对于不带权的图,一条路径的路径长度是指该路径上的边的条数;对于带权的图,一
条路径的路径长度是指该路径上各个边权值的总和。

权值:边附带的数据信息

简单路径与回路:若路径上各顶点v1,v2,v3,…,vm均不重复,则称这样的路径为简单路
径。若路径上第一个顶点v1和最后一个顶点vm重合,则称这样的路径为回路或环。

 子图(顶点和边都是原图的一部分):设图G = {V, E}和图G1 = {V1,E1},若V1属于V且E1属于E,则称G1是G的子图。

连通图(无向图):在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1与顶点v2是连通的。如果图中任意一对顶点都是连通的,则称此图为连通图。

强连通图(有向图):在有向图中,若在每一对顶点vi和vj之间都存在一条从vi到vj的路径,也存在一条从vj到vi的路径,则称此图是强连通图

生成树(无向图):一个连通图的最小连通子图称作该图的生成树。有n个顶点的连通图的生成树有n个顶点和n-1条边。

最小生成树(无向图):生成树中边的权值最小的生成树 ,所谓最小是指边的权值之和小于或者等于其它生成树的边的权值之和。 (后面会介绍最小生成树的相关算法)

1.3 图的一些现实应用

1.3.1 保证连通情况下修路的最小开销(最小生成树)

用最小的代价连通起来。

1.3.2 社交关系 

二、图的存储结构

       因为图中既有节点,又有边(节点与节点之间的关系),因此,在图的存储中,只需要保存:节点和边关系即可。节点保存比较简单,只需要一段连续空间即可,那么通过对关系的保存,从而衍生除了以下两种存储结构——邻接矩阵和邻接表。

2.1 邻接矩阵

      因为节点与节点之间的关系就是连通与否,即为0或者1,因此邻接矩阵(二维数组)即是:先用一个数组将定点保存,然后采用矩阵来表示节点与节点之间的关系。
     

注意:
1. 无向图的邻接矩阵是对称的,第i行(列)元素之和,就是顶点i的度。有向图的邻接矩阵则不一定是对称的,第i行(列)元素之后就是顶点i 的出(入)度(一般来说存的是出度)

2. 如果边带有权值,并且两个节点之间是连通的,上图中的边的关系就用权值代替,如果两个
顶点不通,则使用无穷大(用一个基本上不可能出现的权重)代替

3. 用邻接矩阵存储图的优点是能够快速知道两个顶点是否连通O(1),缺陷是如果顶点比较多,边比
较少时,比较浪费空间,并且(1)要求两个节点之间的路径不是很好求(2)不适合查找一个顶点连接的所有边O(N) 

2.2 邻接矩阵的简单模拟实现

图创建的方式:
        1、io输入  不方便测试 再oj中较为合适
        2、图结构关系写到文件,读取文件
        3、手动去添加边,这样会更方便测试!!

结构:

_vertexs 顶点集合

map<V, size_t> _IndexMap; 顶点和下标的映射 方便通过顶点快速找到下标 然后在邻接矩阵中O(1)拿到权值

vector<vector<W>> _matrix;   // 存储边集合以及对应权值的邻接矩阵

namespace Matrix  //以邻接矩阵的形式封装
{
	template<class V, class W, W MAX_W = INT_MAX, bool Direction = false>   //V表示顶点  W表示权重  MAX_W表示默认的权重值  Direction表示是有向图还是无向图    后面两个是非类型模版参数(缺省) 
	class Graph
	{
		typedef Graph<V, W, MAX_W, Direction> Self;
	public:
		//图创建的方式
		//1、io输入  不方便测试 再oj中较为合适
		//2、图结构关系写到文件,读取文件
		//3、手动去添加边,这样会更方便测试!!
		Graph() = default; //强制生成默认构造

		Graph(const V* vertexs, size_t n) //传一个顶点相关的集合进行初始化
		{
			_vertexs.reserve(n);
			for (size_t i = 0; i < n; ++i) //初始化顶点集合
			{
				_vertexs.push_back(vertexs[i]);//存到顶点集合里
				_IndexMap[vertexs[i]] = i;//建立顶点和下标的映射关系,方便我们进行查找
			}
			//初始化邻接矩阵
			_matrix.resize(n);
			for (auto& e : _matrix)   e.resize(n, MAX_W);
		}

		//获取顶点的下标(为什么要单独给这样一个函数呢?因为可能给的是一个错误的顶点,要检查一下)
		size_t GetVertexIndex(const V& v)
		{
			//有可能顶点会给错,这样在map中就找不到 所以要先检查一下
			auto it = _IndexMap.find(v);
			if (it != _IndexMap.end())  return it->second;
			else
			{
				throw invalid_argument("不存在的顶点");//抛异常(异常被捕获后可以不做处理)
				//断言太暴力了,会直接终止程序,并且断言在release版本下会被屏蔽

				//异常被捕获后可以不作处理,程序从捕获位置继续执行。 而断言是完全无法忽略的,程序在断言失败处立即终止。
				//  因此断言通常用于调试版本,用来发现程序中的逻辑错误。 虽然异常也能起到这样的作用,但是不应该用异常代替断言: 
				// 1) 如果发现了逻辑错误,必须修改程序,而不可能在程序中进行处理和恢复,所以不需要向外传送,没有必要使用异常。
				//  2) 使用断言的开销比异常小得多,而且断言可以从发布版中完全去除。

				return -1; //还是要返回,因为编译器不会在乎运行,而是会检查你在这边有没有返回
			}
		}

		//利用序号为两个节点添加边
		void _AddEdge(size_t srci, size_t dsti, const W& w)
		{
			_matrix[srci][dsti] = w;
			//如果是无向图
			if (Direction == false)   _matrix[dsti][srci] = w;
		}


		//对两个节点添加边,以及权重关系  src代表起点 dst代表中点 w代表权重
		void AddEdge(const V& src, const V& dst, const W& w)
		{
			size_t srci = GetVertexIndex(src);
			size_t dsti = GetVertexIndex(dst);

			_AddEdge(srci, dsti, w);
		}

  void Print()//帮助我们测试
{
	//顶点
	for (size_t i = 0; i < _vertexs.size(); ++i)
		cout << "[" << i << "]" << "->" << _vertexs[i] << endl; //下标映射顶点集合
	cout << endl;

	//打印横一行的下标
	cout << "  ";
	for (size_t i = 0; i < _vertexs.size(); ++i)  cout << i << " ";
	cout << endl;

	//打印矩阵
	for (size_t i = 0; i < _matrix.size(); ++i)
	{
		cout << i << " ";
		for (size_t j = 0; j < _matrix[i].size(); ++j)
			if (_matrix[i][j] == MAX_W) cout << '*' << " ";
			else cout << _matrix[i][j] << " ";
		cout << endl;
	}
	cout << endl;
}
 private:
	map<V, size_t> _IndexMap;    //建立顶点和下标之间的关系,方便我们根据顶点去找他的下标     比如两个顶点是否存在关系,就可以快速找到两个顶点的下标,然后去邻接矩阵看一下
	vector<V> _vertexs;			 // 顶点集合  
	vector<vector<W>> _matrix;   // 存储边集合的矩阵
};
}

2.3 邻接表

邻接表:使用数组表示顶点的集合,使用链表表示边的关系

结构:

_vertexs 顶点集合

map<V, size_t> _IndexMap; 顶点和下标的映射 方便通过顶点快速找到下标 

vector<Edge*> _linktable;  // 存储边集合的邻接表

1. 无向图邻接表存储

2.4 邻接表的简单模拟实现

	namespace LinkTable  //以邻接矩阵的形式封装
	{

		//实现一个边
		template<class W> //边只要存权重即可
		struct Edge
		{
			size_t _srci;//入边
			size_t _dsti;//出边
			W _w;//权重
			Edge<W>* _next;//存下一个边

			Edge(size_t srci ,size_t dsti, const W& w)
				:_srci(srci)
				,_dsti(dsti)
				, _w(w)
				, _next(nullptr)
			{}

		};

template<class V, class W, bool Direction = false>   //V表示顶点  W表示权重    Direction表示是有向图还是无向图    后面两个是非类型模版参数(缺省) 
class Graph
{
	typedef Edge<W> Edge;
public:
	//图创建的方式
	//1、io输入  不方便测试 再oj中较为合适
	//2、图结构关系写到文件,读取文件
	//3、手动去添加边,这样会更方便测试!!
	Graph(const V* vertexs, size_t n) //传一个顶点相关的集合进行初始化
	{
		_vertexs.reserve(n);
		for (size_t i = 0; i < n; ++i) //初始化顶点集合
		{
			_vertexs.push_back(vertexs[i]);//存到顶点集合里
			_IndexMap[vertexs[i]] = i;//建立顶点和下标的映射关系,方便我们进行查找
		}
		_linktable.resize(n, nullptr);//先初始化为空,后面手动去添加边
	}

	//获取顶点的下标(为什么要单独给这样一个函数呢?因为可能给的是一个错误的顶点,要检查一下)
	size_t GetVertexIndex(const V& v)
	{
		//有可能顶点会给错,这样在map中就找不到 所以要先检查一下
		auto it = _IndexMap.find(v);
		if (it != _IndexMap.end())  return it->second;
		else
		{
			throw invalid_argument("不存在的顶点");//抛异常(异常被捕获后可以不做处理)
			//断言太暴力了,会直接终止程序,并且断言在release版本下会被屏蔽

			//异常被捕获后可以不作处理,程序从捕获位置继续执行。 而断言是完全无法忽略的,程序在断言失败处立即终止。
			//  因此断言通常用于调试版本,用来发现程序中的逻辑错误。 虽然异常也能起到这样的作用,但是不应该用异常代替断言: 
			// 1) 如果发现了逻辑错误,必须修改程序,而不可能在程序中进行处理和恢复,所以不需要向外传送,没有必要使用异常。
			//  2) 使用断言的开销比异常小得多,而且断言可以从发布版中完全去除。

			return -1; //还是要返回,因为编译器不会在乎运行,而是会检查你在这边有没有返回
		}
	}


	void _AddEdge(size_t srci, size_t dsti, const W& w)
	{
		Edge* sd_eg = new Edge(srci, dsti, w);

		//头插的逻辑
		sd_eg->_next = _linktable[srci];
		_linktable[srci] = sd_eg;

		//如果是无向图 2->1
		if (Direction == false)
		{
			Edge* ds_eg = new Edge(dsti,srci,w);

			//头插的逻辑
			ds_eg->_next = _linktable[dsti];
			_linktable[dsti] = ds_eg;
		}

	}


	//对两个节点添加边,以及权重关系  src代表起点 dst代表中点 w代表权重
	void AddEdge(const V& src, const V& dst, const W& w)
	{
		size_t srci = GetVertexIndex(src);
		size_t dsti = GetVertexIndex(dst);
		_AddEdge(srci, dsti, w);
	}


	void Print()
	{
		//顶点和下标的映射关系
		for (size_t i = 0; i < _vertexs.size(); ++i)
			cout << "[" << i << "]" << "->" << _vertexs[i] << endl; //下标映射顶点集合
		cout << endl;

		//打印出边表
		cout << "打印出边表:" << endl;
		for (size_t i = 0; i < _linktable.size(); ++i)
		{
			cout << _vertexs[i] << "[" << i << "]->";
			Edge* cur = _linktable[i];
			while (cur)
			{
				cout << _vertexs[cur->_dsti] << "[" << cur->_dsti << "]:" << cur->_w << "->";
				cur = cur->_next;
			}
			cout << "nullptr" << endl;
		}
		cout << endl;
		//打印入边表

	}

private:
	map<V, size_t> _IndexMap;  //建立顶点和下标之间的关系,方便我们根据顶点去找他的下标     比如两个顶点是否存在关系,就可以快速找到两个顶点的下标,然后去邻接矩阵看一下
	vector<V> _vertexs;		   // 顶点集合  
	vector<Edge*> _linktable;

};
}

2.5 邻接矩阵和邻接表的优劣性

最关键的问题就是:1,两个顶点是否相连。2,相连的权值是多少。

邻接矩阵:

1,邻接矩阵的存储方式非常适合稠密图

2,邻接矩阵O(1)判断两个顶点的连接关系,并取到权值

3,不适合查找一个顶点连接的所有边——O(N)

邻接表:

1,邻接表的存储方式非常适合稀疏图

2,适合找一个顶点连出去的所有边

3,不适合确定两点是否相连以及权值——O(N)

三、图的遍历方式

3.1 广度优先遍历

 ​​​​​​

      每访问一个结点,我们就将与他相连的顶点入队列,但是我们在入队列的时候需要用一个标记数组标记一下,这样可以避免 比如说A出的时候,BCD进,而B出的时候ACE进,如果用了标记数组,那么重复的AC就不会再入队列了。

层序遍历 但是没有一层一层出
void BFS(const V& src) //src表示我们的起点
{
	size_t srci = GetVertexIndex(src);//找到起点的下标
	queue<int> q;//存储下标的队列
	size_t n = _vertexs.size();//表示有多少个节点
	vector<bool> check(n);
	q.push(srci);
	check[srci] = true;//入队列就标记
	while (!q.empty())
	{
		int front = q.front();//取队头
		q.pop();
		cout << _vertexs[front] << ":"<<front<<endl;
		//然后让他的朋友进
		for (size_t i = 0; i < n; ++i)
			if (_matrix[front][i] != MAX_W && check[i] == false)
			{
				q.push(i);
				check[i] = true;
			}
	}
}

我们来看看美团的一道经典OJ

   也就是说我们得去找到他的六度好友,方法就是在层序遍历的时候,我们要控制一层一层出!

所以我们将BFS修改一下,控制成一行一行出(类似二叉树的层序遍历控制一行一行出)


		//控制一层一层出 (常见的应用:找几度好友)
		void BFS(const V& src) //src表示我们的起点
		{
			size_t srci = GetVertexIndex(src);//找到起点的下标
			queue<size_t> q;//存储下标的队列
			size_t n = _vertexs.size();//表示有多少个节点
			vector<bool> check(n);
			q.push(srci);
			check[srci] = true;//入队列就标记
			while (!q.empty())
			{
				//控制一层一层出
				size_t sz = q.size();
				for (size_t i = 0; i < sz; ++i) //一层出完了再去走下一层
				{
					size_t front = q.front();//取队头
					q.pop();
					cout << front << ":" << _vertexs[front] << " ";
					//然后让他的朋友进
					for (size_t i = 0; i < n; ++i)
						if (_matrix[front][i] != MAX_W && check[i] == false)
						{
							q.push(i);
							check[i] = true;
						}
				}
				cout << endl;
			}

3.2 深度优先遍历

void _DFS(size_t srci, vector<bool>& check) //下一个位置的起点以及需要一个标记数组
{
	cout << srci << ":" << _vertexs[srci] << " " << endl; //先访问 然后标记为访问过
	check[srci] = true;
	for (size_t i = 0; i < _vertexs.size(); ++i)
		if (_matrix[srci][i] != MAX_W && check[i] == false)
			_DFS(i, check);
}


void DFS(const V& src) //需要有一个起点
{
	size_t srci = GetVertexIndex(src);//找到起点的下标
	vector<bool> check(_vertexs.size()); //标记数组
	_DFS(srci, check);
	//如果是一个非连通图,可以在后面再进行一层检查check数组,然后对false的数组再进行一次访问
}

      如果我们遍历的图并不是连通图 那么最后可能会有一些结点访问不到,所以这个时候我们的解决方案就是遍历一次check数组,如果其中有false,那就以这个false为起点再走深度优先遍历,保证把剩下的结点遍历完。

给大家附上一个测试用例:

void TestGraph2()
{
	string a[] = { "张三", "李四", "王五", "赵六" ,"周七","黑八" };
	int n = sizeof(a) / sizeof(a[0]);
	Graph<string, int> g1(a, n);
	g1.AddEdge("张三", "李四", 100);
	g1.AddEdge("张三", "王五", 200);
	g1.AddEdge("王五", "赵六", 30);
	g1.AddEdge("王五", "周七", 30);
	g1.AddEdge("黑八", "周七", 30);
	g1.Print();
	g1.BFS("张三");
	cout << endl;
	g1.DFS("黑八");

}

 

   下一次博主会重点介绍图论的相关算法!!感谢支持!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1636311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于网络爬虫技术的网络新闻分析参考论文(论文 + 源码)

【免费】基于网络爬虫技术的网络新闻分析系统.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89248815 基于网络爬虫技术的网络新闻分析 摘 要 自从大数据的概念被提出后&#xff0c;互联网数据成为了越来越多的科研单位进行数据挖掘的对象。网络新闻数据占据了…

EasyRecovery2024汉化版电脑数据恢复软件下载

EasyRecovery是一款功能强大的数据恢复软件&#xff0c;其主要功能包括但不限于以下几点&#xff1a; 硬盘数据恢复&#xff1a;能够扫描本地计算机中的所有卷&#xff0c;建立丢失和被删除文件的目录树&#xff0c;实现硬盘格式化、重新分区、误删数据、重建RAID等硬盘数据恢…

RTSP,RTP,RTCP

机器学习 Machine Learning&#xff08;ML&#xff09; 深度学习&#xff08;DL&#xff0c;Deep Learning&#xff09; CV计算机视觉&#xff08;computer vision&#xff09; FFMPEG&#xff0c;MPEG2-TS,H.264,H.265,AAC rstp,rtp,rtmp,webrtc onvif,gb28181 最详细的音…

数智新重庆 | 推进信号升格 打造算力山城

2024年&#xff0c;是实现“十四五”规划目标任务的关键一年&#xff0c;高质量的5G网络、强大的AI能力作为新质生产力的重要组成部分&#xff0c;将有效赋能包括制造业在内的千行万业数字化化、智能化、绿色化转型升级&#xff0c;推动融合应用新业态、新模式蓬勃兴起&#xf…

上传jar到github仓库,作为maven依赖存储库

记录上传maven依赖包到github仓库问题 利用GitHubPackages作为依赖的存储库踩坑1 仓库地址问题踩坑2 Personal access tokens正确姿势一、创建一个普通仓库&#xff0c;比如我这里是fork的腾讯Shadow到本地。地址是&#xff1a;https://github.com/dhs964057117/Shadow二、生成…

Postgresql 从小白到高手 十一 :数据迁移ETL方案

文章目录 Postgresql 数据迁移ETL方案1、Pg 同类型数据库2 、Pg 和 不同数据库 Postgresql 数据迁移ETL方案 1、Pg 同类型数据库 备份 : pg_dump -U username -d dbname -f backup.sql插入数据&#xff1a; psql -U username -d dbname -f backup.sqlpg_restore -U username…

31.Gateway网关-跨域问题

跨域 1.域名不同&#xff1a;www.baidu.com和www.taobao.com,www.taobao.org 2.域名相同&#xff0c;端口不同。localhost:8080和localhost:8081 跨域问题 浏览器禁止请求的发起者与服务端发生跨域ajax请求&#xff0c;请求被浏览器拦截的问题。 解决方案 CORS 浏览器询…

实操——使用uploadify插件(php版和Java版) 与 Dropzone.js插件分别实现附件上传

实操——使用uploadify插件&#xff08;php版和Java版&#xff09;与 Dropzone.js插件分别实现附件上传 1. 使用uploadify插件上传1.1 简介1.1.1 简介1.1.2 参考GitHub 1.2 后端PHP版本的uploadify1.2.1 下载项目的目录结构1.2.2 测试看界面效果1.2.3 附页面代码 和 PHP代码 1.…

操作DOM:性能优化之道

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【webrtc】MessageHandler 3: 基于线程的消息处理:以sctp测试为例

消息处理可以用于模拟发包处理G:\CDN\rtcCli\m98\src\net\dcsctp\socket\dcsctp_socket_network_test.cc 这个实现中,onMessage还是仅对了一种消息进行处理,就是接收则模式下,打印带宽。当然,可能程序有多个消息,分别在不同的onmessage中执行?SctpActor:以一个恒定的速率…

u盘量产工具拥有分区功能,它把一个U盘分成数个移动盘,更改U盘介质类型(Fixed 和 Removabe),供大家学习研究参考~

非常受欢迎的u盘量产工具。最新版拥有分区功能&#xff0c;它把一个U盘分成数个移动盘&#xff0c;更改U盘介质类型(Fixed 和 Removabel)。数码之家量产工具官方版不是数据恢复&#xff0c;是对U盘底层硬件信息的恢复(非硬件损坏)&#xff0c;使因为底层硬件信息受损电脑无法识…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-8.2-链接脚本

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

如何利用仪表构造InfiniBand流量在数据中心测试中的应用

一、什么是Infiniband&#xff1f; 在当今数据爆炸的时代&#xff0c;数据中心作为信息处理的中心枢纽&#xff0c;面临着前所未有的挑战。传统的通信方式已经难以满足日益增长的数据传输需求&#xff0c;而InfiniBand技术的出现&#xff0c;为数据中心带来了全新的通信解决方…

在AndroidStudio创建Flutter项目并运行到模拟器

1.Flutter简介 Flutter是Google开源的构建用户界面&#xff08;UI&#xff09;工具包&#xff0c;帮助开发者通过一套代码库高效构建多平台精美应用&#xff0c;支持移动、Web、桌面和嵌入式平台。Flutter 开源、免费&#xff0c;拥有宽松的开源协议&#xff0c;适合商…

如何提升制造设备文件汇集的可靠性和安全性?

制造设备文件汇集通常指的是将与制造设备相关的各种文档和资料进行整理和归档的过程。这些文件可能包括但不限于&#xff1a; 生产数据&#xff1a;包括生产计划、订单信息、生产进度等。 设计文件&#xff1a;如CAD图纸、设计蓝图、产品模型等。 工艺参数&#xff1a;用于指…

Django后台项目开发实战五

完成两个功能&#xff1a; HR 可以维护候选人信息面试官可以录入面试反馈 第五阶段 创建 interview 应用&#xff0c;实现候选人面试评估表的增删改功能&#xff0c;并且按照页面分组来展示不同的内容&#xff0c;如候选人基础信息&#xff0c;一面&#xff0c;二面的面试结…

如何判断第三方软件测试公司是否具有资质

在软件开发的过程中&#xff0c;软件测试是确保软件质量、稳定性和用户体验的关键环节。许多企业选择将软件测试工作交给专业的第三方软件测试公司来完成&#xff0c;以确保测试的准确性和公正性。但是&#xff0c;如何判断一个第三方软件测试公司是否具有资质呢&#xff1f;以…

第11章 数据库技术(第一部分)

一、数据库技术术语 &#xff08;一&#xff09;术语 1、数据 数据描述事物的符号描述一个对象所用的标识&#xff0c;可以文字、图形、图像、语言等等 2、信息 现实世界对事物状态变化的反馈。可感知、可存储、可加工、可再生。数据是信息的表现形式和载体&#xff0c;信…

基于肤色模型的人脸识别FPGA实现,包含tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 matlab2022a的测试结果如下&#xff1a; vivado2019.2的仿真结果如下&#xff1a; 将数据导入到matlab中&#xff0c; 系统的RTL结构图如下图所示…

Guitar Pro8中文最新免费版吉他编曲学习软件下载

Guitar Pro 8是一款专业的吉他编曲学习软件&#xff0c;支持多种乐器。具体来说&#xff0c;它支持所有的4至8弦的弹拨乐器&#xff0c;包括但不限于吉他、贝斯、班卓琴、曼陀铃等。此外&#xff0c;它还支持鼓、钢琴、尤克里里等乐器。因此&#xff0c;无论是初学者还是高手&a…