图【数据结构】

文章目录

  • 图的基本概念
  • 邻接矩阵
  • 邻接表
  • 图的遍历
    • BFS
    • DFS

图的基本概念

图是由顶点集合及顶点间的关系组成的一种数据结构
顶点和边:图中结点称为顶点

权值:边附带的数据信息

在这里插入图片描述

在这里插入图片描述
路径 : 在这里插入图片描述

简单路径 和 回路:在这里插入图片描述

子图:设图G = {V, E}和图G1 = {V1,E1},若V1属于V且E1属于E,则称G1是G的子图
在这里插入图片描述

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

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

生成树就是用最少的边连通起来

最小生成树:构成生成树这些边加起来权值是最小的。

顶点的度:
**加粗样式**
在这里插入图片描述

邻接矩阵

在这里插入图片描述

#pragma once 
#include<map>
#include<vector>
#include<algorithm>
#include<assert.h>
#include<string>
#include <functional>
#include<iostream>
using namespace std;
//矩阵 
namespace matrix
{
	//V是顶点 ,W是 weight 权值 
	template <class V, class W, W MAX_W = INT_MAX, bool Direction = false>  //true是有向图 ,false是无向图
	class Graph
	{
	public:
		//手动添加边
		Graph(const V* a, size_t n)  //用指针数组 存储顶点
		{
			_vertex.reserve(n);
			//初始化顶点和边
			for (size_t i = 0; i < n; i++)
			{
				_vertex.push_back(a[i]);
				_indexMap[a[i]] = i; //通过顶点找下标
			}
			_matrix.resize(n);
			for (size_t i = 0; i < n; i++)
			{
				//将邻接矩阵的权值设置为最大值
				_matrix[i].resize(n, MAX_W);
			}
		}
		size_t  GetVertexIndexMap(const V& v)
		{
			auto  it = _indexMap.find(v);
			if (it != _indexMap.end())
			{
				return it->second;
			}
			else //没有找到 
			{
				assert(false);
				return -1;
			}
		}

		void AddEdge(const V& src, const V& dst, const W& w)
		{
			int srci = GetVertexIndexMap(src);
			int dsti = GetVertexIndexMap(dst);

			_matrix[srci][dsti] = w;
			//无向图 
			if (Direction == false)
			{
				_matrix[srci][dsti] = w;
				_matrix[dsti][srci] = w;

			}

		}
			void  Print()
			{

				//顶点 
				for (int i = 0; i < _vertex.size(); i++)
				{
					cout << "[" << i << "]" << "->" << _vertex[i] << endl;
				}
				//矩阵 
				cout << endl;

				//打印横下标
				cout << "  ";
				for (size_t i = 0; i < _vertex.size(); i++)
				{
					cout << i << " ";
				}
				cout << endl;

				for (int i = 0; i < _matrix.size(); i++)
				{
					cout << i << " ";//打印竖下标
					for (int j = 0; j < _matrix[0].size(); j++)

					{
						if (_matrix[i][j] == MAX_W)
						{
							cout << "*"<<" ";
						}
						else
						{
							cout << _matrix[i][j] <<" ";
						}
					}
					cout << endl;
				}
			}
	
public:
	vector<V> _vertex;  //顶点集合 
	map<V, int>  _indexMap;					//顶点映射下标 
	vector< vector<W> >	 _matrix;					//邻接矩阵

};


	void TestGraph()
	{
		Graph<char, int, INT_MAX, true> g("0123", 4);
		g.AddEdge('0', '1', 1);
		g.AddEdge('0', '3', 4);
		g.AddEdge('1', '3', 2);
		g.AddEdge('1', '2', 9);
		g.AddEdge('2', '3', 8);
		g.AddEdge('2', '1', 5);
		g.AddEdge('2', '0', 3);
		g.AddEdge('3', '2', 6);
		g.Print();
	}
}



邻接表

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

出边表:存储从各个顶点连接出去的边,出边表中下标为 i的位置存储的是从编号为i的顶点连接出去的边

入边表:存储连接到各个顶点的边,入边表中下标为i的位置存储的是连接到编号为 i的顶点的边
在这里插入图片描述
出边表和入边表的其中每个位置存储的都是一个链表
出边表中下标为i的位置表示从编号为i的顶点连接出去的边
入边表中下标为i 的位置表示连接到编号为i 的顶点的边

在实现邻接表时,一般只需要用一个出边表来存储从各个顶点连接出去的边即可,因为大多数情况下都是需要从一个顶点出发找与其相连的其他顶点,所以一般不需要存储入边表

//邻接表
namespace link_table
{
	template<class  W>
	struct Edge
	{
		int _dsti;//目标点的下标 
		W _w;//权值
		Edge<W> *_next; //用链表表示边的关系

		Edge(int dsti, const W& w)
			:_dsti(dsti)
			, _w(w)
			, _next(nullptr)  
		{

		}

	};
	//V是顶点 ,W是 weight 权值 
	
	template <class V, class W, bool Direction = false>  //true是有向图 ,false是无向图
	class Graph
	{
	public:
		typedef Edge<W> Edge;
		//手动添加边
		Graph(const V* a, size_t n)  //用指针数组 存储顶点
		{
			_vertex.reserve(n);
			//初始化顶点和边
			for (size_t i = 0; i < n; i++)
			{
				_vertex.push_back(a[i]);
				_indexMap[a[i]] = i; //通过顶点找下标
			}
			_table.resize(n, nullptr);
		
		}
		size_t  GetVertexIndexMap(const V& v)
		{
			auto  it = _indexMap.find(v);
			if (it != _indexMap.end())
			{
				return it->second;
			}
			else //没有找到 
			{
				assert(false);
				return -1;
			}
		}

		void AddEdge(const V& src, const V& dst, const W& w)
		{
			int srci = GetVertexIndexMap(src); 
			int dsti = GetVertexIndexMap(dst);

			//头插
			Edge *eg = new Edge(dsti,w);
			//有向图 
			//添加从源顶点到目标顶点的边
			eg->_next = _table[srci];
			_table[srci] = eg;
			

			



			//无向图 

			//添加从目标顶点到源顶点的边
			if (Direction == false)
			{
				//????
				Edge* eg = new Edge(srci, w);
				eg->_next = _table[dsti];
				_table[dsti] = eg;
			}


	

		}
		void  Print()
		{

			//顶点 
			for (int i = 0; i < _vertex.size(); i++)
			{
				cout << "[" << i << "]" << "->" << _vertex[i] << endl;
			}
			cout << endl;
			
			//遍历顶点
			for (size_t i = 0; i < _vertex.size(); i++)
			{
				cout << _vertex[i] << endl;
			}
			//遍历邻接表的目标点的下标和权值 

			for (size_t i = 0; i < _table.size(); i++)
			{
				cout << _vertex[i] << "[" << i << "]->";
				Edge * cur = _table[i];
				while (cur != nullptr)
				{
					cout << "[" << _vertex[cur->_dsti] << ":" << cur->_dsti << ":" << cur->_w << "]->";
					cur = cur->_next;
				}
				cout << "nullptr" << endl;
			}
		}

	public:
		vector<V> _vertex;  //顶点集合 
		map<V, int>  _indexMap;					//顶点映射下标 
		vector<  Edge*>	 _table;					//邻接表

	};


	void TestGraph()
	{
		string a[] = { "张三", "李四", "王五", "赵六" };
		Graph<string, int, true> g1(a, 4);
		g1.AddEdge("张三", "李四", 100);
		g1.AddEdge("张三", "王五", 200);
		g1.AddEdge("王五", "赵六", 30);
		g1.Print();
	}
}

图的遍历

BFS

在这里插入图片描述


			void BFS(const V& src)  //遍历顶点,通过下标找顶点
			{

				size_t srci = GetVertexIndexMap(src);
				queue<int>  q;

				vector<bool>  v(_vertex.size(), false);  //防止走重复的路

				q.push(srci);

				v[srci] = true;
				while (!q.empty())
				{
						int front = q.front();
						q.pop();
						cout << _vertex[front] << endl;
						// 把front顶点的邻接顶点的下标入队列
						for (size_t i = 0; i < _vertex.size(); i++)
						{
							if (_matrix[front][i] != MAX_W && v[i] == false)
							{
								q.push(i);
								v[i] = true;
							}
						}
					
				}
			}

DFS

在这里插入图片描述


			void _DFS(    size_t srci  ,vector<bool> & v)
			{

				cout << srci << ":" << _vertex[srci] << endl;
				v[srci] = true;

				// 找一个srci相邻的没有访问过的点,去往深度遍历
				for (int i =0 ; i< _vertex.size()  ; i++ )
				{
					if (v[i] ==false && _matrix[srci][i] != MAX_W)
					{
						_DFS(i ,v);
					}
				}

			}
			void  DFS(const V& src) //遍历顶点,通过下标找顶点
			{
				
				vector<bool>  v(_vertex.size(), false);  //防止走重复的路
				size_t  srci = GetVertexIndexMap(src);
				_DFS(srci, v);

			}

完整测试代码

#pragma once 
#include<map>
#include<vector>
#include<algorithm>
#include<assert.h>
#include<string>
#include <functional>
#include<iostream>
#include<queue>
using namespace std;
//矩阵 
namespace matrix
{
	//V是顶点 ,W是 weight 权值 
	//连通的,边的关系就用权值代替,如果两顶点不通,则使用无穷大代替
	template <class V, class W, W MAX_W = INT_MAX, bool Direction = false>  //true是有向图 ,false是无向图
	class Graph
	{
	public:
		//手动添加边
		Graph(const V* a, size_t n)  //用指针数组 存储顶点
		{
			_vertex.reserve(n);
			//初始化顶点和边
			for (size_t i = 0; i < n; i++)
			{
				_vertex.push_back(a[i]);
				_indexMap[a[i]] = i; //通过顶点找下标
			}
			_matrix.resize(n);
			for (size_t i = 0; i < n; i++)
			{
				//将邻接矩阵的权值设置为最大值
				_matrix[i].resize(n, MAX_W);
			}
		}
		size_t  GetVertexIndexMap(const V& v)
		{
			auto  it = _indexMap.find(v);
			if (it != _indexMap.end())
			{
				return it->second;
			}
			else //没有找到 
			{
				assert(false);
				return -1;
			}
		}

		void AddEdge(const V& src, const V& dst, const W& w)
		{
			int srci = GetVertexIndexMap(src);
			int dsti = GetVertexIndexMap(dst);

			_matrix[srci][dsti] = w;
			//无向图 
			if (Direction == false)
			{
				_matrix[srci][dsti] = w;
				_matrix[dsti][srci] = w;

			}

		}
			void  Print()
			{

				//顶点 
				for (int i = 0; i < _vertex.size(); i++)
				{
					cout << "[" << i << "]" << "->" << _vertex[i] << endl;
				}
				//矩阵 
				cout << endl;

				//打印横下标
				cout << "  ";
				for (size_t i = 0; i < _vertex.size(); i++)
				{
					cout << i << " ";
				}
				cout << endl;

				for (int i = 0; i < _matrix.size(); i++)
				{
					cout << i << " ";//打印竖下标
					for (int j = 0; j < _matrix[0].size(); j++)

					{
						if (_matrix[i][j] == MAX_W)
						{
							cout << "*"<<" ";
						}
						else
						{
							cout << _matrix[i][j] <<" ";
						}
					}
					cout << endl;
				}
			}


			void BFS(const V& src)  //遍历顶点,通过下标找顶点
			{

				size_t srci = GetVertexIndexMap(src);
				queue<int>  q;

				vector<bool>  v(_vertex.size(), false);  //防止走重复的路

				q.push(srci);

				v[srci] = true;
				while (!q.empty())
				{
						int front = q.front();
						q.pop();
						cout << _vertex[front] << endl;
						// 把front顶点的邻接顶点的下标入队列
						for (size_t i = 0; i < _vertex.size(); i++)
						{
							if (_matrix[front][i] != MAX_W && v[i] == false)
							{
								q.push(i);
								v[i] = true;
							}
						}
					
				}
			}

			void _DFS(    size_t srci  ,vector<bool> & v)
			{

				cout << srci << ":" << _vertex[srci] << endl;
				v[srci] = true;

				// 找一个srci相邻的没有访问过的点,去往深度遍历
				for (int i =0 ; i< _vertex.size()  ; i++ )
				{
					if (v[i] ==false && _matrix[srci][i] != MAX_W)
					{
						_DFS(i ,v);
					}
				}

			}
			void  DFS(const V& src) //遍历顶点,通过下标找顶点
			{
				
				vector<bool>  v(_vertex.size(), false);  //防止走重复的路
				size_t  srci = GetVertexIndexMap(src);
				_DFS(srci, v);

			}
	
public:
	vector<V> _vertex;  //顶点集合 
	map<V, int>  _indexMap;					//顶点映射下标 
	vector< vector<W> >	 _matrix;					//邻接矩阵

};


	void TestGraph()
	{
		Graph<char, int, INT_MAX, true> g("0123", 4);
		g.AddEdge('0', '1', 1);
		g.AddEdge('0', '3', 4);
		g.AddEdge('1', '3', 2);
		g.AddEdge('1', '2', 9);
		g.AddEdge('2', '3', 8);
		g.AddEdge('2', '1', 5);
		g.AddEdge('2', '0', 3);
		g.AddEdge('3', '2', 6);
		g.Print();
	}


	void TestBDFS()
	{
		string a[] = { "张三", "李四", "王五", "赵六", "周七" };
		Graph<string, int> g1(a, sizeof(a) / sizeof(string));
		g1.AddEdge("张三", "李四", 100);
		g1.AddEdge("张三", "王五", 200);
		g1.AddEdge("王五", "赵六", 30);
		g1.AddEdge("王五", "周七", 30);
		g1.Print();

		//g1.BFS("张三");
		g1.DFS("张三");
	}
}

//邻接表
namespace link_table
{
	template<class  W>
	struct Edge
	{
		int _dsti;//目标点的下标 
		W _w;//权值
		Edge<W> *_next; //用链表表示边的关系

		Edge(int dsti, const W& w)
			:_dsti(dsti)
			, _w(w)
			, _next(nullptr)  
		{

		}

	};





	//V是顶点 ,W是 weight 权值 
	
	template <class V, class W, bool Direction = false>  //true是有向图 ,false是无向图
	class Graph
	{
	public:
		typedef Edge<W> Edge;
		//手动添加边
		Graph(const V* a, size_t n)  //用指针数组 存储顶点
		{
			_vertex.reserve(n);
			//初始化顶点和边
			for (size_t i = 0; i < n; i++)
			{
				_vertex.push_back(a[i]);
				_indexMap[a[i]] = i; //通过顶点找下标
			}
			_table.resize(n, nullptr);
		
		}
		size_t  GetVertexIndexMap(const V& v)
		{
			auto  it = _indexMap.find(v);
			if (it != _indexMap.end())
			{
				return it->second;
			}
			else //没有找到 
			{
				assert(false);
				return -1;
			}
		}

		void AddEdge(const V& src, const V& dst, const W& w)
		{
			int srci = GetVertexIndexMap(src); 
			int dsti = GetVertexIndexMap(dst);

			//头插
			Edge *eg = new Edge(dsti,w);
			//有向图 
			//添加从源顶点到目标顶点的边
			eg->_next = _table[srci];
			_table[srci] = eg;
			

			



			//无向图 

			//添加从目标顶点到源顶点的边
			if (Direction == false)
			{
				//????
				Edge* eg = new Edge(srci, w);
				eg->_next = _table[dsti];
				_table[dsti] = eg;
			}


	

		}
		void  Print()
		{

			//顶点 
			for (int i = 0; i < _vertex.size(); i++)
			{
				cout << "[" << i << "]" << "->" << _vertex[i] << endl;
			}
			cout << endl;
			
			//遍历顶点
			for (size_t i = 0; i < _vertex.size(); i++)
			{
				cout << _vertex[i] << endl;
			}


			//遍历邻接表的目标点的下标和权值 

			for (size_t i = 0; i < _table.size(); i++)
			{
				cout << _vertex[i] << "[" << i << "]->";
				Edge * cur = _table[i];
				while (cur != nullptr)
				{
					cout << "[" << _vertex[cur->_dsti] << ":" << cur->_dsti << ":" << cur->_w << "]->";
					cur = cur->_next;
				}
				cout << "nullptr" << endl;
			}


		}

	public:
		vector<V> _vertex;  //顶点集合 
		map<V, int>  _indexMap;					//顶点映射下标 
		vector<  Edge*>	 _table;					//邻接表

	};


	void TestGraph()
	{
		string a[] = { "张三", "李四", "王五", "赵六" };
		Graph<string, int, true> g1(a, 4);
		g1.AddEdge("张三", "李四", 100);
		g1.AddEdge("张三", "王五", 200);
		g1.AddEdge("王五", "赵六", 30);
		g1.Print();
	}
}
	

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络:关键性能指标与非性能特征解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

VR文化旅游虚拟现实介绍|虚拟现实元宇宙|VR设备购买

虚拟现实&#xff08;VR&#xff09;技术正在改变我们对文化旅游的认知和体验。通过VR技术&#xff0c;人们可以身临其境地探索世界各地的文化遗产和旅游景点&#xff0c;无需亲临现场也能感受到逼真的体验。以下是VR文化旅游虚拟现实的介绍&#xff1a; 身临其境的体验&#x…

c++之旅——第六弹

大家好啊&#xff0c;这里是c之旅第六弹&#xff0c;跟随我的步伐来开始这一篇的学习吧&#xff01; 如果有知识性错误&#xff0c;欢迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 创作不易&#xff0c;希望大家多多支持哦&#xff01; 一,静态成员&…

安装Mysql和Mycli插件

一、安装数据库 1.重定向生成配置文件 cat >/etc/yum.repos.d/mysql.repo <<EOF [mysql57-community] nameMySQL 5.7 Community Server baseurlhttp://repo.mysql.com/yum/mysql-5.7-community/el/7/x86_64/ enabled1 gpgcheck0 EOF 2.yum安装 yum -y install mysq…

eclipse导入项目出现中文乱码

eclipse导入java项目的时候有时会出现乱码问题&#xff0c;很苦恼&#xff0c;网上找了很多方法都没用&#xff0c;所以得自己记录一下。导入项目可参考链接 eclipse中导入java项目-CSDN博客 1、点击 Windows --> Pereferences 2、依次点击下图内流程 3、看到下面的就修改成…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的血细胞智能检测与计数(深度学习模型+UI界面代码+训练数据集)

摘要&#xff1a;开发血细胞智能检测与计数系统对于疾病的预防、诊断和治疗具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个血细胞智能检测与计数系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&a…

弧形导轨的设计要求

制造业设备种类越来越多&#xff0c;非标自动化设备渐渐成了主力市场&#xff0c;其中弧形导轨线体作为非标自动化运输中的基石&#xff0c;承担了运输&#xff0c;定位&#xff0c;特殊工位组装&#xff0c;其设计要求也非常严格。 1、精度要求&#xff1a;弧形导轨需要具备高…

【C++】开源:iceoryx通信中间件配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍iceoryx通信中间件配置与使用。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新…

Linux运维之管理工具篇

一、前言 因运维过程中&#xff0c;经常会借助于很多工具来实现我们的监控、备份、校验&#xff0c;安全测试&#xff0c;批量操作&#xff0c;可视化辅助&#xff0c;集中管理等&#xff0c;甚至AI相关&#xff0c;本文特对常用工具进行梳理记录&#xff0c;以备不时之需及后…

记OnlyOffice的两个大坑

开发版&#xff0c;容器部署&#xff0c;试用许可已安装。 word&#xff0c;ppt&#xff0c;excel均能正常浏览。 自带的下载菜单按钮能用。 但config里自定义的downloadAs方法却不一而足。 word能正常下载&#xff0c;excel和ppt都不行。 仔细比对调试了代码。发现app.js…

2024年3月份实时获取地图边界数据方法,省市区县街道多级联动【附实时geoJson数据下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

Antd中s-table组件某字段进行排序

Antd中s-table组件某字段进行排序 提前说明&#xff0c;s-table组件包含分页等功能 <s-tableref"table":columns"columns":data"loadData"bordered:row-key"(record) > record.id"></s-table>而其中loadData为获取表数…

strcat函数

函数理解记忆&#xff1a;str表示是<string.g>中的函数&#xff0c;cat表示附加。意思是将一个字符串的内容附加到另一个字符串的末尾。 注意要点&#xff1a;既然要附加&#xff0c;附加的字符串和被附加的字符串都要有\0。否则不知道附加多少&#xff0c;不知附加在哪…

【Linux进程的知识点】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档文章目录 前言 操作系统的知识补充 我们来理解一个用户操作接口&#xff1a; 进程的理解 进程的基本概念 描述进程-PCB task_struct-PCB的一种 task_ struct内容分类 …

算法刷题Day8 | 344.反转字符串、541. 反转字符串II、卡码网:54.替换数字、151.翻转字符串里的单词、卡码网:55.右旋转字符串

目录 0 引言1 反转字符串1.1 我的解题1.2 2 反转字符串II2.1 解题 3 替换数字3.1 双指针法 4 翻转字符串里的单词4.1 我的解题思路4.2 另一种思路 5 右旋转字符串5.15.2 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a5; 标题…

什么是序列化?为什么需要序列化?

1、典型回答 序列化(Serialization)序列化是将对象转换为可存储或传输的形式的过程(例如: 将对象转换为字节流) 反序列化(Deserialization) 是将序列化后的数据(例如: 二进制文件)转换回原始对象的过程。通过反序列化&#xff0c;可以从存储介质 (如磁盘、数据库) 或通过网络…

程序员们的“薪饭碗”鸿蒙迎来“薪”的就业岗位

随着科技行业的不断创新和发展&#xff0c;程序员们所面对的技术挑战和机遇也在不断增加。近年来&#xff0c;鸿蒙操作系统的崛起为程序员们提供了新的就业机会和发展前景。 鸿蒙系统作为一种全新的操作系统&#xff0c;在市场上占据一席之地。在当前就业市场中&#xff0c;鸿…

网络套接字-UDP服务器

一 预备知识 1 端口号和进程id 主机间的数据传输本质是两个进程在通信&#xff0c;就像是我们打开抖音刷视频&#xff0c;视频不是都保存在手机上的&#xff0c;而是服务器发送给你的&#xff0c;这里就是用到了网络。 那如何保证把数据给指定进程呢? 就是用端口号去标识主机中…

[实战]API防护破解之签名验签

前言&#xff1a; 传统的接口在传输的过程中&#xff0c;是非常容易被抓包进行篡改&#xff0c;从而进行中间人攻击。这时候我们可以通过对参数进行签名验证&#xff0c;如果参数与签名值不匹配&#xff0c;则请求不通过&#xff0c;直接返回错误信息&#xff0c;从而防止黑客…

Java错误:微服务报错Cannot execute request on any known serve

&#x1f414;问题内容 报Cannot execute request on any known server 这个错&#xff1a;连接Eureka服务端地址不对。 &#x1f414;解决方式 检查.yml文件或者.properties文件配置 下划线下划线后面的小写字母等同于去掉下划线大写下划线后面的字母&#xff08;驼峰原则&am…