【高阶数据结构】图详解第一篇:图的基本概念及其存储结构(邻接矩阵和邻接表)

文章目录

  • 1. 图的基本概念
    • 1.1 什么是图
    • 1.2 有向图和无向图
    • 1.3 完全图
    • 1.4 邻接顶点
    • 1.5 顶点的度
    • 1.6 路径
    • 1.7 路径长度
    • 1.8 简单路径与回路
    • 1.9 子图
    • 1.10 连通图
    • 1.11 强连通图
    • 1.12 生成树
  • 2. 图的存储结构
    • 2.1 邻接矩阵
    • 2.2 邻接矩阵代码实现
      • 结构定义
      • 构造函数
      • 添加边
      • 打印图
      • 测试
    • 2.3 邻接表
    • 2.4 邻接表代码实现
      • 结构定义
      • 构造函数
      • 添加边
      • 打印图
      • 测试
  • 3. 源码
    • 3.1 Graph.h
    • 3.2 Test.cpp

这篇文章开始,我们来学习一种高阶数据结构——图

1. 图的基本概念

1.1 什么是图

图是由顶点集合及顶点间的关系(边)组成的一种数据结构:G = (V, E)。
其中:
顶点集合V = {x|x属于某个数据对象集}是有穷非空集合;
E = {(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)是有方向的。

顶点和边:

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

1.2 有向图和无向图

图分为有向图和无向图

有向图中,顶点对<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>。

简单总结一下:

图是一种非线性的数据结构,用于表示元素之间的关系。它由节点(也称为顶点)和连接节点的边组成。每个节点可以与其他节点直接或间接连接,这些连接关系可以具有方向性(有向图)或无方向性(无向图)。因此,图可用于表示各种关系,如网络、社交关系、地图等,并且在计算机科学和现实生活中有广泛的应用。

1.3 完全图

在有n个顶点的无向图中,若有n * (n-1)/2条边,即任意两个顶点之间有且仅有一条边,则称此图为无向完全图,比如上图G1
在这里插入图片描述
在n个顶点的有向图中,若有n * (n-1)条边,即任意两个顶点之间有且仅有两条方向相反的边,则称此图为有向完全图,比如上图G4
在这里插入图片描述

1.4 邻接顶点

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

1.5 顶点的度

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

1.6 路径

在图G = (V, E)中,若从顶点vi出发有一组边使其可到达顶点vj,则称顶点vi到顶点vj的顶点序列为从顶点vi到顶点vj的路径。
在这里插入图片描述
比如,在上面这个有向图中,顶点1到顶点7的路径有:
1,3,6,7
1,4,7
可能有多条

1.7 路径长度

对于不带权的图,一条路径的路径长度是指该路径上的边的条数;对于带权的图,一条路径的路径长度是指该路径上各个边权值的总和
在这里插入图片描述

1.8 简单路径与回路

若路径上各顶点v1,v2,v3,…,vm均不重复,则称这样的路径为简单路径。
若路径上第一个顶点v1和最后一个顶点vm重合,则称这样的路径为回路或环。
在这里插入图片描述

1.9 子图

设图G = {V, E}和图G1 = {V1,E1},若V1属于V且E1属于E,则称G1是G的子图(即G1的顶点和边都是原图的一部分)
在这里插入图片描述

1.10 连通图

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

1.11 强连通图

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

1.12 生成树

无向图中,一个连通图的最小连通子图称作该图的生成树。
有n个顶点的连通图的生成树有n个顶点和n-1条边。
比如:
在这里插入图片描述

2. 图的存储结构

因为图中既有节点,又有边(节点与节点之间的关系),因此,在图的存储中,只需要保存:节点和边关系即可。
节点保存比较简单,只需要一段连续空间即可,那边关系该怎么保存呢?

2.1 邻接矩阵

首先我们来学习图的第一种存储结构——邻接矩阵

那邻接矩阵是如何保存图的顶点和边呢?

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

比如:
在这里插入图片描述

值为1就表示对应的这两个顶点是连通的,为0就表示两个顶点不连通

那其实观察上面的图我们可以发现:

无向图的邻接矩阵是对称的,第i行(列)元素之和,就是顶点i的度(边没有权值,只存0/1的情况下,元素和就是度)
有向图的邻接矩阵则不一定是对称的,第i行(列)元素之和就是顶点i 的出(入)度(边没有权值,只存0/1的情况下)

另外呢:

1. 如果边带有权值,并且两个节点之间是连通的,上图中的边的关系(1/0)就用权值代替,如果两个顶点不通,可以使用无穷大代替(后面我们实现的时候就要增加一个表示无穷大的模板参数)
在这里插入图片描述
2. 用邻接矩阵存储图的优点是能够快速知道两个顶点是否连通,取到权值
3. 缺陷是如果顶点比较多,边比较少时,矩阵中存储了大量的0成为系数矩阵,比较浪费空间;所以邻接矩阵比较适合存储稠密图(边比较多的图),不适合存储稀疏图(边比较少的图)
而且要求两个节点之间的路径不好求;
还有求一个顶点相连的顶点有哪些也不好求(O(N),这个用后面的邻接表结构存储的话就很好求)。

2.2 邻接矩阵代码实现

那下面我们就来实现一下邻接矩阵:

结构定义

那我们这里呢还是搞成模板,因为顶点的值可以是任意类型,那我们的模板都需要给哪些参数呢?

在这里插入图片描述
这里我们先给了3个模板参数,解释一下:
V接收顶点(vertex)的类型,W接收权值的类型(权值不一定非得是整数),然后我们再给一个非类型模板参数来决定我们要定义的图是有向图还是无向图(比如Direction==false就是无向图,等于true就是有向图),一般用无向图居多,所以可以给个缺省值false,我们不传默认就是无向图。

那现在图里面要存顶点和边:

顶点呢我们就可以用一个vector来存储。
在这里插入图片描述
那边我们要如何存呢?
上面有提到邻接矩阵是用一个二维数组(即矩阵)来存储边(顶点之间的关系)的,我们可以再来看一下图
在这里插入图片描述
那这里就涉及到一个问题:
这里面二维数组的每一个下标是不是都要跟一个顶点进行映射啊。
比如二维数组中某一个元素_vertexs[i][j]是1,那就表示下标ij对应的两个顶点是连通的。
那怎么建立顶点和数组下标的映射呢?
🆗,我们上一篇文章并查集里面其实就讲了一种方法,我们当时说了图里面也会用到。
用一个map就搞定了嘛。
在这里插入图片描述

构造函数

然后我们来想一下构造函数可以怎么写?

那我们可以这样搞:
创建一个图对象的时候可以先把顶点存一些,给一个顶点的数组就可以,然后后面我们可以再增加一个增加边的接口,我们可以手动创建边和赋权值。
所以,构造函数
在这里插入图片描述
就可以这样写

添加边

然后我们来增加一个添加边的接口:

在这里插入图片描述
那首先我们要获取一下顶点的下标,因为我们添加边其实就是在邻接矩阵里面改这两个顶点对应位置的值嘛
可以再封装一个接口
在这里插入图片描述
然后AddEdge里面我们就可以获取两个顶点对应的下标然后在邻接矩阵里面添加边
在这里插入图片描述
然后添加边这里有一个问题
我们的代码是要同时针对有向图和无向图的,如果是无向图的话我们添加一条边比如AB,那就完了;但是如果是有向图添加AB就是AB,如果要添加BA的就需要再添加一次。
所以我们这样写:
在这里插入图片描述

打印图

然后我们再写一个打印,搞些数据测试一波:

在这里插入图片描述

测试

来测试一下
在这里插入图片描述
我们就以这个为例
在这里插入图片描述
运行一下
在这里插入图片描述
没问题,只不过上面图中ij相等的位置打印的是0

2.3 邻接表

邻接表:

使用数组存储顶点的集合,使用链表存储顶点的关系(边)。

比如
无向图邻接表存储:

在这里插入图片描述
一个顶点与哪些顶点相连,相连的顶点就存到这个顶点对应的链表中,当然如果带权的话也要存上对应边的权值。
(每个顶点都有一个对应的链表,多条链表用一个指针数组就可以维护起来)
注意:无向图中同一条边在邻接表中出现了两次。如果想知道顶点vi的度,只需要知道顶点vi 对应链表集合中结点的数目即可

有向图邻接表存储:

在这里插入图片描述

那通过上面的了解其实我们可以得出,对于邻接表的存储方式

1. 适合存储稀疏图(边比较少的图),因为邻接表的话有多少边链表里面就存几个对应的顶点,不需要额外的空间;而上面邻接矩阵不论边多边少都要开一个N*N的矩阵(二维数组),边少的时候那就大部分位置都存的是0
2. 方便查找从一个顶点连接出去的边有哪些,因为它对应的边链表里面存的就是与这个顶点相连的顶点
3. 但是不方便确定两个顶点是否相连和获取权值(要遍历其中一个顶点的边链表查找O(N))

2.4 邻接表代码实现

那我们再来实现一下邻接表。

结构定义

首先来定义一下邻接表的结构:

在这里插入图片描述
首先对于邻接表来说,模板参数这里就不需要MAX_W这个非类型模板参数了。
因为上面邻接矩阵之所以需要是因为矩阵不相连的边矩阵里面对应得位置要存这个值来标识一下,但是邻接表我们上面了解了,每个顶点连接的边有多少,就存多少个顶点,不相连的顶点直接是不存的。
然后呢顶点我们还是用一个vector来存,还要建立顶点根下标的映射(每个顶点要跟指针数组的下标一一对应),与邻接矩阵不同的在于这里的边要用链表来存,一个顶点与哪些顶点相连,相连的顶点就存到这个顶点对应的边链表中。
如果带权的话还要存上权值,所以我们可以把边链表封装成一个类:
在这里插入图片描述
其实就是一个链表的结构,因为我们要用链表来存储边嘛
然后,图的结构里面
在这里插入图片描述
邻接表其实就是一个指针数组嘛,每个位置存一个指针,指针指向一个链表,该位置的下标就映射对应的顶点,对应的链表里面存的就是与之相连的顶点以及对应边的权值
在这里插入图片描述

构造函数

那下面我们来写一下邻接表结构图的构造函数:

逻辑其实根上面邻接矩阵是一样的
在这里插入图片描述

添加边

然后添加边:

首先还是获取一下边的起始顶点和终止顶点映射的下标在这里插入图片描述
然后添加边的时候:
如果是无向图,比如添加一个边AB,那要在A的链表里面挂B顶点,也要在B的链表里面挂A顶点;
如果是有向图,只在A的链表里面挂B就行了(当然有向图的话我们看到上面还分为出边表和入边表,但是入边表一般不需要搞,我们这里就只存一个出边表,有需要的话可以再添加)

所以呢,添加的逻辑我们这样写:

在这里插入图片描述

打印图

那我们再来写个打印的函数,然后测试一下

在这里插入图片描述
这个函数没什么难度,就不解释了

测试

然后我们来搞一组数据测试一下:

在这里插入图片描述
我们这里不传第三个模板参数,默认是无向图
看一下结果
在这里插入图片描述
没问题!
我们也可以试一下有向图
在这里插入图片描述
也没问题!

3. 源码

3.1 Graph.h

#pragma once//邻接矩阵
namespace matrix
{template<class V, class W, W MAX_W = INT_MAX, bool Direction = false>class Graph{public:Graph(const V* ver, size_t n){//存储顶点并与下标建立映射_vertexs.reserve(n);for (size_t i = 0; i < n; i++){_vertexs.push_back(ver[i]);_indexMap[ver[i]] = i;}//给邻接矩阵开空间_matrix.resize(n);for (auto& e : _matrix){e.resize(n, MAX_W);}}size_t GetVertexIndex(const V& v){auto it = _indexMap.find(v);if (it != _indexMap.end()){return it->second;}else{throw invalid_argument("顶点不存在");return -1;}}void AddEdge(const V& src, const V& dst, const W& w){size_t srci = GetVertexIndex(src); size_t dsti = GetVertexIndex(dst);_matrix[srci][dsti] = w;if (Direction == false)//无向图{_matrix[dsti][srci] = w;}}void Print(){// 打印顶点和下标映射关系for (size_t i = 0; i < _vertexs.size(); ++i){cout << _vertexs[i] << "-" << i << " ";}cout << endl << 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 << _matrix[i][j] << " ";elsecout << "#" << " ";}cout << endl;}cout << endl << endl; 打印所有的边//for (size_t i = 0; i < _matrix.size(); ++i)//{//	for (size_t j = 0; j < _matrix[i].size(); ++j)//	{//		if (i < j && _matrix[i][j] != MAX_W)//		{//			cout << _vertexs[i] << "-" << _vertexs[j] << ":" << _matrix[i][j] << endl;//		}//	}//}}private:vector<V> _vertexs;//顶点集合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();}
}//邻接表
namespace link_table
{template<class W>struct Edge{int _dsti;//边的终止顶点下标W _w;     //权值Edge<W>* _next;Edge(const int& dsti, const W& w):_dsti(dsti),_w(w),_next(nullptr){}};template<class V, class W, bool Direction = false>class Graph{typedef Edge<W> Edge;public:Graph(const V* ver, size_t n){//存储顶点并与下标建立映射_vertexs.reserve(n);for (size_t i = 0; i < n; i++){_vertexs.push_back(ver[i]);_indexMap[ver[i]] = i;}//给邻接表开空间_tables.resize(n, nullptr);}size_t GetVertexIndex(const V& v){auto it = _indexMap.find(v);if (it != _indexMap.end()){return it->second;}else{throw invalid_argument("顶点不存在");return -1;}}void AddEdge(const V& src, const V& dst, const W& w){size_t srci = GetVertexIndex(src);size_t dsti = GetVertexIndex(dst);//src->dstEdge* eg = new Edge(dsti, w);eg->_next = _tables[srci];_tables[srci] = eg;//如果是无向图,再添加反向边dst->srcif (Direction == false){Edge* eg = new Edge(srci, w);eg->_next = _tables[dsti];_tables[dsti] = eg;}}void Print(){// 打印顶点for (size_t i = 0; i < _vertexs.size(); ++i){cout << "[" << i << "]" << "->" << _vertexs[i] << endl;}cout << endl;//遍历打印每个顶点的边链表for (size_t i = 0; i < _tables.size(); ++i){cout << _vertexs[i] << "[" << i << "]->";Edge* cur = _tables[i];while (cur){cout << "[" << _vertexs[cur->_dsti] << ":" << cur->_dsti << ":" << cur->_w << "]->";cur = cur->_next;}cout << "nullptr" << endl;}}private:vector<V> _vertexs;//顶点集合map<V, int> _indexMap;//顶点和下标建立映射vector<Edge*> _tables;	// 邻接表};void TestGraph(){string a[] = { "张三", "李四", "王五", "赵六" };Graph<string, int, true> g1(a, 4);g1.AddEdge("张三", "李四", 100);g1.AddEdge("张三", "王五", 200);g1.AddEdge("王五", "赵六", 30);g1.Print();}
}

3.2 Test.cpp

#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <map>
#include <string>
#include "Graph.h"int main()
{//matrix::TestGraph();link_table::TestGraph();return 0;
}

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

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

相关文章

ToBeWritten之改进威胁猎杀:自动化关键角色与成功沟通经验

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

10款录屏软分析与选择使用,只看这篇文章就轻松搞定所有,高清4K无水印录屏,博主UP主轻松选择

录屏软件整理 如下为录屏软件&#xff0c;通过思维导图展示分析介绍&#xff1a; https://www.drawon.cn/template/details/6522bd5e0dad9029a0b528e1 如下为整理的录屏软件列表 名称产地价格支持的平台下载地址说明OBS国外免费开源windows/linux/machttps://obsproject.co…

linux 笔记:远程服务器登录jupyter notebook

1 生成jupyter notebook 配置文件&#xff08;服务器端&#xff09; jupyter notebook --generate-config #Writing default config to: /home/shuailiu/.jupyter/jupyter_notebook_config.py2 Ipython中设置密码&#xff08;服务器端&#xff09; 3 修改jupyter 配置文件&…

汇编语言是怎么一回事?

汇编语言基础 汇编指令和机器码的区别 数据的表示 各类汇编指令 数据传送和算法运算 位运算 条件分支指令 函数调用 字符串处理 流水线和指令调度 流水线实现指令级并行 编译器指令调度 CPU乱序与投机执行 汇编器将汇编语言翻译成 CPU 可以执行的机器码&#xff0c…

强烈推荐这5款功能强大的小软件

​ 今日的栽种&#xff0c;明日的果实&#xff0c;今天继续分享五个功能强大的小软件。 1.文本编辑——IDM UltraEdit ​ IDM UltraEdit是一款功能强大的文本编辑器&#xff0c;它支持多种编程语言和文件格式&#xff0c;可以处理大型文件&#xff0c;进行代码折叠&#xff0…

reactjs开发环境搭建

Reactjs是一个前端web页面应用开发框架工具集&#xff0c;其支持前端构建页面以及后端构建页面两种常用的开发场景&#xff0c;其中&#xff0c;支持reactjs的开发框架包括next.js、remix、gatsby以及其他&#xff0c;本文主要描述next.js开发环境的搭建&#xff0c;next.js是一…

c++中的map和set

文章目录 1. 关联式容器2. 键值对3. 树形结构的关联式容器3.1 set3.1.1 set的介绍3.1.2 set的使用 3.2 map3.2.1 map的介绍3.2.2 map的使用 3.3 multiset3.3.1 multiset的介绍3.3.2 multiset的使用 3.4 multimap3.4.1 multimap的介绍3.4.2 multimap的使用 1. 关联式容器 在初阶…

java socket实现代理Android App

实现逻辑就是转发请求和响应。 核心代码 // 启动代理服务器private void startProxyServer() {new Thread(new ProxyServer()).start();}// 代理服务器static class ProxyServer implements Runnable {Overridepublic void run() {try {// 监听指定的端口int port 8098; //一…

CSS 实现:常见布局

1 设备与视口 设备屏幕尺寸是指屏幕的对角线长度。像素是计算机屏幕能显示一种特定颜色的最小区域&#xff0c;分为设备像素和逻辑像素。 在 Apple 的视网膜屏&#xff08;Retina&#xff09;中&#xff0c;默认每 4 个设备像素为一组&#xff0c;渲染出普通屏幕中一个像素显示…

HTML5+CSS3+JS小实例:鼠标滚轮水平滚动

实例:鼠标滚轮水平滚动 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content="…

《游戏编程模式》学习笔记(十二)类型对象 Type Object

定义 定义类型对象类和有类型的对象类。每个类型对象实例代表一种不同的逻辑类型。 每种有类型的对象保存对描述它类型的类型对象的引用。 定义往往不是人能看懂的&#xff0c;我们需要例子才能够理解。 举例 假设你要为一款游戏制作一些怪物敌人。这些敌人有不同的血量及攻…

Stable Diffusion云服务器部署完整版教程

Stable Diffusion云服务器部署完整版教程 2023年07月04日 22:30 3607浏览 18喜欢 22评论 <span class"bili-avatar-icon bili-avatar-right-icon "></span> </div>薯片_AI 粉丝&#xff1a; 1513 文章&#xff1a; 1 设置分组取消关注 已关注 …

四位十进制频率计VHDL,DE1开发板验证,仿真和源码

名称&#xff1a;四位十进制频率计VHDL&#xff0c;DE1开发板验证 软件&#xff1a;Quartus 语言&#xff1a;VHDL 要求&#xff1a; 数字频率计设计要求 1、四位十进制数字显示的数学式频率计,其频率测量范围为10~9999khz,测量单位为kHz。 2、要求量程能够转换。即测几十…

CDN体系架构及部署方案探索

如今是科技技术飞速发展的时代&#xff0c;特别是互联网技术在各个方面都得到了质的提升。对于CDN技术来说&#xff0c;该项技术的基本功能、体系构架以及运营部署等方面都取得了长足的发展&#xff0c;不仅技术日新月异&#xff0c;而且整个体系日趋成熟&#xff0c;并且不断朝…

Tasmota系统之外设配置

Tasmota系统之外设配置 &#x1f388;相关篇《ESP32/ESP8266在线刷写Sonoff Tasmota固件以及配置简要》&#x1f516;这里以ESP32配置DS18B20温度传感器和dht11温湿度传感器为例。 ✨如果想接特定型号的显示屏幕&#xff0c;需要下载指定的固件&#xff0c;目前官方所提供的固件…

学计算机Java和c语言哪个出路比较好?

学计算机Java和c语言哪个出路比较好&#xff1f; 首先&#xff0c;这两者相比来说&#xff0c;个人更推荐你学习Java。 C比较复杂一些&#xff0c;难学一些。 Java相对于更适合大多数人&#xff0c;适合非高等学府出来的人。 第一、按Java目前的需求来说最近很多小伙伴找我&…

jar 命令启动java 指定配置文件路径 jar如何启动

一、各种启动方式 1.java -jar # 例子 java -jar test.jar 1. 2. 这是最简单的启动方式&#xff0c;同时弊端也是很多的。 弊端1&#xff1a;exit 退出终端会导致java进程中断。 弊端2&#xff1a;ctrlc 退出启动展示页会导致java进程中断。 弊端3&#xff1a;直接关闭终端会…

P1540 [NOIP2010 提高组] 机器翻译(模拟)

[NOIP2010 提高组] 机器翻译 题目背景 小晨的电脑上安装了一个机器翻译软件&#xff0c;他经常用这个软件来翻译英语文章。 题目描述 这个翻译软件的原理很简单&#xff0c;它只是从头到尾&#xff0c;依次将每个英文单词用对应的中文含义来替换。对于每个英文单词&#xf…

多功能频率计周期/脉宽/占空比/频率测量verilog,视频/代码

名称&#xff1a;多功能频率计周期、脉宽、占空比、频率测量verilog 软件&#xff1a;Quartus 语言&#xff1a;Verilog 代码功能&#xff1a; 多功能频率计&#xff0c;可测量信号的周期、脉冲宽度、占空比、频率&#xff0c;语言为verilog&#xff0c;quartus软件设计仿真…

Text embedding 模型总结

文章目录 MTEB榜单8个嵌入任务三种数据集类别 C_METB榜单文本向量表示模型 目前&#xff0c;随着 Langchain LLM模型 的火热&#xff0c;除了层出不穷的大模型外&#xff0c;因为检索的能力会很大程度影响最终的问答效果&#xff0c;文本的嵌入模型也是大家比较关注的。本文主…