C++关联容器1——关联容器概述,map,set介绍,pair类型

关联容器

关联容器支持高效的关键字查找和访问。

两个主要的关联容器(associative-container)类型是map和set。

map中的元素是一些关键字一值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。

set 中每个元素只包含一个关键字;set 支持高效的关键字查询操作——检查一个给定关键字是否在set中。

例如,在某些文本处理过程中,可以用一个set 来保存想要忽略的单词。字典则是一个很好的使用map的例子:可以将单词作为关键字,将单词释义作为值。

标准库提供8个关联容器

关联容器类型——按关键字有序保存元素
map关联数组;保存关键字-值对
set关键字即值,即只保存关键字的容器
multimap关键字可重复出现的map
multiset关键字可重复出现的set
关联容器类型——无序集合
unordered_map用哈希函数组织的map
unordered_set用哈希函数组织的set
unordered_multimap哈希组织的map;关键字可以重复出现
unordered _multiset哈希组织的set;关键字可以重复出现

这8个容器间的不同体现在三个维度上;

每个容器

  1. 或者是一个set,或者是一个map;
  2. 或者要求不重复的关键字,或者允许重复关键字;
  3. 按顺序保存元素,或无序保存。

允许重复关键字的容器的名字中都包含单词multi;不保持关键字按顺序存储的容器的名字都以单词unordered开头。

因此一个 unordered_multi_set是一个允许重复关键字,元素无序保存的集合,而一个set则是一个要求不重复关键字,有序存储的集合。无序容器使用哈希函数来组织元素,

类型map和multimap 定义在头文件map中;set和multiset定义在头文件set中;无序容器则定义在头文件 unordered_map和 unordered_set中。

使用关联容器

虽然大多数程序员都熟悉诸如vector和1ist这样的数据结构,但他们中很多人从未使用过关联数据结构。在学习标准库关联容器类型的详细内容之前,我们首先来看一个如何使用这类容器的例子,这对后续学习很有帮助。

map 是关键字——值对的集合。

例如,可以将一个人的名字作为关键字,将其电话号码作为值。我们称这样的数据结构为“将名字映射到电话号码”。

map类型通常被称为关联数组(associative array)。关联数组与“正常”数组类似,不同之处在于其下标不必是整数。我们通过一个关键字而不是位置来查找值。也就是说,我们把关键字当成下标来用。给定一个名字到电话号码的map,我们可以使用一个人的名字作为下标来获取此人的电话号码。

与之相对,set就是关键字的简单集合。当只是想知道一个值是否存在时,set 是最有用的。例如,一个企业可以定义一个名为bad_checks的set 来保存那些曾经开过空头支票的人的名字。在接受一张支票之前,可以查询bad_checks 来检查顾客的名字是否在其中。

使用map

#include <iostream>  
#include <map>  
#include <string>  int main() {  // 创建一个空的map,键是string类型,值是int类型  std::map<std::string, int> myMap;  // 插入元素  myMap["apple"] = 1;  myMap["banana"] = 2;  myMap["cherry"] = 3;  // 访问元素//把关键字当成下标来用  std::cout << "The number of apples is: " << myMap["apple"] << std::endl;  // 使用迭代器遍历map  for (std::map<std::string, int>::iterator it = myMap.begin(); it != myMap.end(); ++it) {  std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;  }  // 使用C++11的基于范围的for循环遍历map  for (const auto& pair : myMap) {  std::cout << "Key: " << pair.first << ", Value: " << pair.second << std::endl;  }  // 查找元素  if (myMap.find("banana") != myMap.end()) {  std::cout << "Banana found in the map!" << std::endl;  }  // 修改元素  myMap["apple"] = 10;  // 删除元素  myMap.erase("banana");  // 检查map是否为空  if (myMap.empty()) {  std::cout << "The map is empty." << std::endl;  } else {  std::cout << "The map is not empty." << std::endl;  }  return 0;  
}

这个示例展示了如何使用std::map执行基本的操作,如插入、访问、遍历、查找、修改和删除元素。注意,由于map中的键是唯一的,如果你尝试插入具有相同键的新元素,该键的值将被新值覆盖。 

类似顺序容器,关联容器也是模板。

为了定义一个map,我们必须指定关键字和值的类型。

在此程序中,map保存的每个元素中,关键字是string类型,值是int类型。

当从map中提取一个元素时,会得到一个pair类型的对象,我们将在下面介绍它。

简单来说,pair是一个模板类型,保存两个名为first 和secona的(公有)数据成员。

map所便用的pair用first 成员保存关键字,用second成员保存对应的值。

因此,输出语句的效果是打印每个单词及其关联的计数器。

使用set

在C++中,std::set是一个关联容器,它包含唯一的元素,这些元素默认按照升序排列。std::set中的元素是唯一的,并且总是按键(即元素的值)排序。以下是一个使用std::set的简单示例:

#include <iostream>  
#include <set>  
#include <string>  int main() {  // 创建一个空的set,元素类型为string  std::set<std::string> mySet;  // 插入元素  mySet.insert("apple");  mySet.insert("banana");  mySet.insert("cherry");  // 尝试插入重复的元素,将不会改变set  mySet.insert("apple"); // 这个操作是无效的,因为"apple"已经在set中  // 访问元素(注意:set不提供直接通过索引访问元素的功能)  // 但可以遍历所有元素  for (const auto& element : mySet) {  std::cout << element << ' ';  }  std::cout << std::endl;  // 查找元素  if (mySet.find("banana") != mySet.end()) {  std::cout << "Banana found in the set!" << std::endl;  }  // 删除元素  mySet.erase("banana");  // 再次遍历set以验证元素已被删除  for (const auto& element : mySet) {  std::cout << element << ' ';  }  std::cout << std::endl;  // 检查set是否为空  if (mySet.empty()) {  std::cout << "The set is empty." << std::endl;  } else {  std::cout << "The set is not empty." << std::endl;  }  // 获取set的大小  std::cout << "The size of the set is: " << mySet.size() << std::endl;  return 0;  
}

这个示例展示了如何使用std::set执行基本的操作,如插入、遍历、查找、删除元素以及检查set是否为空。由于std::set中的元素是唯一的,因此插入重复的元素是无效的。另外,std::set不提供通过索引直接访问元素的功能,因为它是基于红黑树实现的,元素在内存中的位置可能会随着插入和删除操作而变化。相反,你需要使用迭代器来遍历std::set中的元素。 

关联容器概述

关联容器(有序的和无序的)都支持http://t.csdnimg.cn/moE16 中介绍的普通容器操作。

关联容器不支持顺序容器的位置相关的操作,例如push_front或pushback。

原因是关联容器中元素是根据关键字存储的,这些操作对关联容器没有意义。而且,关联容器也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作。

除了与顺序容器相同的操作之外,关联容器还支持一些顺序容器不支持的操作和类型别名。此外,无序容器还提供一些用来调整哈希性能的操作。

关联容器的迭代器都是双向的。

定义关联容器

  • 当定义一个map时,必须既指明关键字类型又指明值类型;
  • 而定义一个set时,只需指明关键字类型,因为set中没有值。

每个关联容器都定义了一个默认构造函数,它创建一个指定类型的空容器。

我们也可以将关联容器初始化为另一个同类型容器的拷贝,或是从一个值范围来初始化关联容器,只要这些值可以转化为容器所需类型就可以。

在新标准下,我们也可以对关联容器进行值初始化:

map<string, size_t> word count;//空容器
//列表初始化
set<string> exclude =
{"the","but","and","or","an","a",
"The","But","And","Or","An","A"};map<string, string> authors = { {"Joyce","James"},{"Austen","Jane"},{"Dickens","Charles"}};//三个元素;authors将姓映射为名

与以往一样,初始化器必须能转换为容器中元素的类型。对于set,元素类型就是关键字类型。

当初始化一个map时,必须提供关键字类型和值类型。我们将每个关键字一值对包围在花括号中:

{key, value}

来指出它们一起构成了map中的一个元素。在每个花括号中,关键字是第一个元素,值是第二个。因此,authors将姓映射到名,初始化后它包含三个元素。

初始化multimap或multiset

一个map或set中的关键字必须是唯一的,即,对于一个给定的关键字,只能有一个元素的关键字等于它。

容器multimap和multiset没有此限制,它们都允许多个元素具有相同的关键字。

例如,在我们用来统计单词数量的map中,每个单词只能有一个元素。另一方面,在一个词典中,一个特定单词则可具有多个与之关联的词义。

下面的例子展示了具有唯一关键字的容器与允许重复关键字的容器之间的区别;首先,我们将创建一个名为ivec的保存int的vector,它包含20个元素:0到9每个整数有两个拷贝。我们将使用此vector 初始化一个 set 和一个multiset:

//定义一个有20个元素的vector,保存0到9每个整数的两个拷贝
vector<int> ivec;for (vector<int>::size_type i = 0; i != 10; ++i) 
{
ivec.push back(i);
ivec.push back(i);//每个数重复保存一次
}//iset 包含来自ivec的不重复的元素;miset包含所有20个元素
set<int> iset(ivec.cbegin(), ivec.cend());
multiset<int> miset(ivec.cbegin(), ivec.cend());cout << ivec.size() << endl;//打印出20
cout << iset.size() << endl;//打印出10
cout << miset.size() << endl;//打印出20

即使我们用整个ivec 容器来初始化iset,它也只含有10个元素:对应ivec中每个不同的元素。另一方面,miset有20个元素,与ivec中的元素数量一样多。

关键字类型的要求

关联容器对其关键字类型有一些限制。 

对于有序容器——map、multimap、set以及multiset,关键字类型必须定义元素比较的方法。

默认情况下,标准库使用关键字类型的<运算符来比较两个关键字。

在集合类型中,关键字类型就是元素类型;在映射类型中,关键字类型是元素的第一部分的类型。

 std::map<std::string, int> myMap;  

这个的关键字是string

传递给排序算法的可调用对象必须满足与关联容器中关键字一样的类型要求

有序容器的关键字类型

可以向一个算法提供我们自己定义的比较操作,与之类似,也可以提供自己定义的操作来代替关键字上的<运算符。

所提供的操作必须在关键字类型上定义一个严格弱序。

可以将严格弱序看作“小于等于”,虽然实际定义的操作可能是一个复杂的函数。

无论我们怎样定义比较函数,它必须具备如下基本性质:

  1. 两个关键字不能同时“小于等于”对方;如果k1“小于等于”k2,那么k2绝不能“小于等于”k1。
  2. 如果x1“小于等于”k2,且k2“小于等于”k3,那么k1必须“小于等于”k3。
  3. 如果存在两个关键字,任何一个都不“小于等于”另一个,那么我们称这两个关键字是“等价”的。如果k1“等价于”k2,且k2“等价于”k3,那么k1必须“等价于”k3。

如果两个关键字是等价的(即,任何一个都不“小于等于”另一个),那么容器将它们视作相等来处理。当用作map的关键字时,只能有一个元素与这两个关键字关联,我们可以用两者中任意一个来访问对应的值。

在实际编程中,重要的是,如果一个类型定义了“行为正常”的<运算符,则它可以用作关键字类型。

使用关键字类型的比较函数

用来组织一个容器中元素的操作的类型也是该容器类型的一部分。

为了指定使用自定义的操作,必须在定义关联容器类型时提供此操作的类型。

如前所述,用尖括号指出要定义哪种类型的容器,自定义的操作类型必须在尖括号中紧跟着元素类型给出。

在尖括号中出现的每个类型,就仅仅是一个类型而已。

当我们创建一个容器(对象)时,才会以构造函数参数的形式提供真正的比较操作(其类型必须与在尖括号中指定的类型相吻合)。

在C++中,如果你希望为关联容器(如std::mapstd::setstd::multimapstd::multiset)指定自定义的操作,比如自定义比较函数或函数对象(仿函数),你可以在定义容器类型时作为第三个模板参数来提供。

这个第三个参数通常是一个可调用对象,它决定了容器中的元素如何进行比较以决定排序和唯一性。

#include <iostream>  
#include <set>  
#include <functional> // 为了使用 std::less 或 std::greater  // 自定义比较函数  
struct MyLess {  bool operator()(const int& a, const int& b) const {  return a > b; // 注意这里我们使用了大于操作符,使得set中的元素按降序排列  }  
};  int main() {  // 使用自定义比较函数的std::set  std::set<int, MyLess> mySet;  // 插入元素  mySet.insert(1);  mySet.insert(3);  mySet.insert(2);  // 遍历set  for (const auto& element : mySet) {  std::cout << element << ' ';  }  std::cout << std::endl;  // 输出:因为使用了自定义的比较函数MyLess,set中的元素会按降序排列  // 输出:3 2 1  return 0;  
}

在这个例子中,我们定义了一个名为MyLess的结构体,它重载了operator()以提供自定义的比较逻辑。然后,在定义std::set<int, MyLess>时,我们将MyLess作为比较类型的实例传递给std::set。因此,mySet中的元素会根据MyLess的比较逻辑进行排序和检查唯一性。在这个例子中,我们使用了大于操作符,所以std::set中的元素会按降序排列。

注意,你不需要总是从头开始编写自定义比较函数。C++标准库已经提供了std::lessstd::greater等预定义的仿函数,你可以直接使用它们,或者将它们作为基础来编写更复杂的比较逻辑。例如,你可以通过std::greater<int>直接指定降序排列的比较函数。

 pair 类型

在介绍关联容器操作之前,我们需要了解名为pair的标准库类型,它定义在头文件utility中。

一个pair保存两个数据成员。

类似容器,pair 是一个用来生成特定类型的模板。

当创建一个pair时,我们必须提供两个类型名,pair的数据成员将具有对应的类型。两个类型不要求一样:

pair<string, string> anon;//保存两个stringpair<string, size_t> word_count;//保存一个string和一个size_tpair<string, vector<int>> line;//保存string和vector<int>

pair的默认构造函数对数据成员进行值初始化。

因此,anon是一个包含两个空string的pair,line 保存一个空string 和一个空vector。wordcount中的size_t成员值为0,而string成员被初始化为空。

我们也可以为每个成员提供初始化器:

pair<string, string> author{"James", "Joyce"};

这条语句创建一个名为author的pair,两个成员被初始化为"James"和"Joyce"。

与其他标准库类型不同,pair的数据成员是public的。

两个成员分别命名为first和second。我们用普通的成员访问符号来访问它们

在C++中,std::pair是一个模板类,用于将两个可能不同类型的值组合成一个单一的实体。这个类有两个公共数据成员,分别命名为firstsecond,你可以使用点运算符(.)或箭头运算符(->,如果pair是指针的话)来访问它们。

下面是一个简单的例子,展示了如何创建std::pair并访问其firstsecond成员:

#include <iostream>  
#include <utility> // 包含std::pair  int main() {  // 创建一个std::pair,其中first是int类型,second是double类型  std::pair<int, double> myPair = {42, 3.14159};  // 使用点运算符访问first和second成员  std::cout << "First: " << myPair.first << std::endl;  std::cout << "Second: " << myPair.second << std::endl;  // 如果你有一个指向std::pair的指针,你可以使用箭头运算符  std::pair<int, double>* ptrToPair = &myPair;  std::cout << "First (via pointer): " << ptrToPair->first << std::endl;  std::cout << "Second (via pointer): " << ptrToPair->second << std::endl;  return 0;  
}

pair 上的操作
pair<Tl, T2> p;p是一个pair,两个类型分别为T1和T2的成员都进行了值初始化
pair<Tl, T2> p(vl, v2)p是一个成员类型为T1和 T2的pair; first和second成员分别用v1和v2进行初始化
pair<Tl,T2>p ={vl,v2};等价于p(v1,v2)
make_pair(v1, v2)返回一个用v1和v2初始化的pair。pair的类型从v1和v2的类型推断出来
p.first返回p的名为first的(公有)数据成员
p.second返回p的名为second的(公有)数据成员
p1 relop p2关系运算符(<、>、<=、>=)按字典序定义:例如,当p1.first<p2.first或!(p2.first<pl.first) && p1.second<p2.second成立时,p1<p2为true。关系运算利用元素的<运算符来实现
p1 != p2当first和second成员分别相等时,两个pair 相等。相等性判断利用元素的==运算符实现

创建pair 对象的函数

想象有一个函数需要返回一个pair。在新标准下,我们可以对返回值进行列表初始化

#include <iostream>  
#include <utility> // 包含std::pair  // 函数返回一个std::pair<int, std::string>  
std::pair<int, std::string> getPair() {  // 使用列表初始化来初始化并返回pair  return {42, "answer"};  
}  int main() {  // 调用函数并接收返回的pair  std::pair<int, std::string> result = getPair();  // 访问并打印pair的成员  std::cout << "First: " << result.first << std::endl;  std::cout << "Second: " << result.second << std::endl;  return 0;  
}

在较早的C++版本中,不允许用花括号包围的初始化器来返回pair这种类型的对象,必须显式构造返回值:

#include <iostream>  
#include <utility> // 包含std::pair  // 函数显式构造并返回一个std::pair<int, std::string>  
std::pair<int, std::string> getPairExplicit() {  // 显式调用std::pair的构造函数  return std::pair<int, std::string>(42, "answer");  
}  

我们还可以用make_pair来生成pair对象,pair的两个类型来自于make _pair的参数:

#include <iostream>  
#include <utility> // 包含std::pair和std::make_pair  // 函数使用std::make_pair来返回一个std::pair<int, std::string>  
std::pair<int, std::string> getPairWithMakePair() {  // 使用std::make_pair来创建pair对象  return std::make_pair(42, "answer");  
} 


 

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

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

相关文章

内网安全-代理Socks协议路由不出网后渗透通讯CS-MSF控制上线简单总结

我这里只记录原理&#xff0c;具体操作看文章后半段或者这篇文章内网渗透—代理Socks协议、路由不出网、后渗透通讯、CS-MSF控制上线_内网渗透 代理-CSDN博客 注意这里是解决后渗透通讯问题&#xff0c;之后怎么提权&#xff0c;控制后面再说 背景 只有win7有网&#xff0c;其…

26 JavaScript学习:JSON和void

JSON 英文全称 JavaScript Object NotationJSON 是一种轻量级的数据交换格式。JSON是独立的语言JSON 易于理解。 JSON 实例 简单的 JSON 字符串实例: "{\"name\": \"Alice\", \"age\": 25, \"city\": \"San Francisco\&…

PX4二次开发快速入门(三):自定义串口驱动

文章目录 前言 前言 软件&#xff1a;PX4 1.14.0稳定版 硬件&#xff1a;纳雷NRA12&#xff0c;pixhawk4 仿照原生固件tfmini的驱动进行编写 源码地址&#xff1a; https://gitee.com/Mbot_admin/px4-1.14.0-csdn 修改 src/drivers/distance_sensor/CMakeLists.txt 添加 add…

Servlet详解(从xml到注解)

文章目录 概述介绍作用 快速入门Servelt的执行原理执行流程&#xff1a;执行原理 生命周期概述API 服务器启动&#xff0c;立刻加载Servlet对象(理解)实现Servlet方式(三种)实现Servlet接口实现GenericServlet抽象类&#xff0c;只重写service方法实现HttpServlet实现类实现Htt…

蓝桥杯-路径之谜

题目描述 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。城堡里面什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡的地面时n*n个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或者纵向移动&#xff0c;但是不能斜着走&#x…

整数的表示和运算

目录 无符号整数 有符号整数 原码表示 原码的缺点 原码-->反码-->补码的转换 原码,补码快速转换技巧(手算) 补码的加法计算 补码的减法计算 总结 无符号整数 无符号整数,即"自然数",0,1,2,3,4,.... C语言中的无符号整数: unsigned short a 1; //无符…

Spark Stream

一、Spark Streaming是什么 Spark Streaming 用于流式数据的处理。Spark Streaming 支持的数据输入源很多&#xff0c;例如&#xff1a;Kafka、Flume、Twitter、ZeroMQ 和简单的 TCP 套接字等等。数据输入后可以用 Spark 的高度抽象原语如&#xff1a;map、reduce、join、wind…

C++ | Leetcode C++题解之第67题二进制求和

题目&#xff1a; 题解&#xff1a; class Solution { public:string addBinary(string a, string b) {string ans;reverse(a.begin(), a.end());reverse(b.begin(), b.end());int n max(a.size(), b.size()), carry 0;for (size_t i 0; i < n; i) {carry i < a.siz…

算法学习系列(五十五):背包模型(三)

目录 引言一、潜水员二、背包问题求具体方案三、机器分配四、开心的今明五、金明的预算方案 引言 今天介绍的是背包模型&#xff0c;还是以题目的形式来介绍的。主要讲了背包问题求方案&#xff0c;就是由最优方案递推回去即可。还有就是一些比较经典的背包问题&#xff0c;其…

im即时通讯源码/仿微信app源码+php即时通讯源码带红包+客服+禁言等系统php+uniapp开发

即时通讯(IM)系统是现代互联网应用中不可或缺的一部分&#xff0c;它允许用户进行实时的文本、语音、视频交流。随着技术的发展&#xff0c;IM系统的功能越来越丰富&#xff0c;如红包、客服、禁言等。本文将探讨如何使用PHP语言开发一个功能完备的即时通讯系统&#xff0c;包括…

逻辑漏洞:Cookie脆弱性导致的逻辑漏洞

前几天学习了逻辑漏洞中的越权漏洞和支付漏洞&#xff0c;今天学习一下cookie脆弱性导致的逻辑漏洞 还是和之前一样&#xff0c;所有内容都是参考别的大佬总结好的&#xff0c;我只是在这里进行学习练习 1、cookie介绍 用户在客户端 (一般为浏览器) 中访问某个页面 &#xff0…

电脑崩溃了,之前备份的GHO文件怎么恢复到新硬盘?

前言 之前咱们说到用WinPE系统给电脑做一个GHO镜像备份&#xff0c;这个备份可以用于硬盘完全崩溃换盘的情况下使用。 那么这个GHO镜像文件怎么用呢&#xff1f; 咱们今天详细来讲讲&#xff01; 如果你的电脑系统硬盘崩溃了或者是坏掉了&#xff0c;那么就需要使用之前备份…

华为机考入门python3--(20)牛客20- 密码验证合格程序

分类&#xff1a;字符串 知识点&#xff1a; 遍历字符串的每个字符 for char in my_str: 可以直接比较字符范围 a < char < z 列表统计元素个数 my_list.count(elem) 寻找子串 my_str.find(sub_str) 题目来自【牛客】 import re import sysdef check_…

【算法】唯一分解定理及最lcm和gcd关系 宝石组合

前言 今天在做一道宝石组合的题目时了解到了这个定理&#xff0c;还是蛮有意思的。 思想 唯一分解定理&#xff1a; 对于任何正整数n&#xff0c;有 n p 1 a 1 p 2 a 2 . . . p k a k n p_1^{a1} \times p_2^{a2} \times ... \times p_k^{ak} np1a1​p2a2​...pkak​ …

C语言零基础快速入门视频教程

C语言零基础快速入门视频教程 介绍C语言C语言零基础视频教程领取教程下期更新预报 介绍C语言 C语言零基础快速入门&#xff1a;探索C语言的起源、特性与魅力 在编程世界中&#xff0c;C语言犹如一座古老而坚实的桥梁&#xff0c;连接着计算机科学的过去与现在。作为一门历史悠…

家庭用水安全新举措:保障自来水管和储水设施卫生

随着公众对家庭用水安全意识的提高&#xff0c;如何确保自来水管和楼顶储水罐的安全性和卫生已成为家庭生活中的重要议题。近期&#xff0c;专家针对此问题提出了一系列实用的注意事项和建议。 注意事项&#xff1a; 定期检查&#xff1a;专家强调&#xff0c;家庭应每季度至…

分布式事务—> seata

分布式事务之Seata 一、什么是分布式事务&#xff1f; 分布式事务是一种特殊类型的事务&#xff0c;它涉及多个分布式系统中的节点&#xff0c;包括事务的参与者、支持事务的服务器、资源服务器以及事务管理器。 在分布式事务中&#xff0c;一次大型操作通常由多个小操作组成…

如何查公网IP?

在网络通信中&#xff0c;每个设备都被分配一个独特的IP地址&#xff0c;用于在Internet上进行标识和通信。公网IP是指可以直接从Internet上访问的IP地址&#xff0c;也称为全局IP。通过查公网IP&#xff0c;我们可以了解我们的设备在Internet上的位置和连接状态。 2. 查公网IP…

vue3使用echarts做树图tree

vue3使用echarts做树图tree 1.安装echarts npm install echarts --save2.在main.js引入 import * as echarts from echarts // 全局方法 app.config.globalProperties.$echarts echarts3.使用 <div id"myChart" :style"{ width: 1000px, height: 1000px …

Django后台项目开发实战五

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