【C++】容器篇(五)—— map和set的基本介绍

序言:

在之前,我们已经对STL中的 序列式容器 进行了相关的学习。本期,我将给大家介绍的则是另外一类容器 —— 关联式容器 !!!


目录

(一)容器回顾

💨【顺序容器】

💨【关联式容器】

💨【容器适配器】

(二)键值对

(三)树形结构的关联式容器

1、set

 1️⃣基本介绍

2️⃣set的使用

2、multiset

 1️⃣ 基本介绍

2️⃣ multiset的使用

3、map

 1️⃣基本介绍

2️⃣ map的使用

4、multimap

1️⃣基本介绍

2️⃣ multimap的使用

(四)在OJ中的使用

 1、前k个高频单词

2、两个数组的交集

总结


(一)容器回顾


在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list 等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别?
 

接下来,我先带大家回顾一下有关容器的一些基本知识,帮助大家唤醒一些“远古”的记忆!

容器可以用于存放各种类型的数据(基本类型的变量,对象等)的数据结构,都是模板类:分为顺序容器、关联式容器、容器适配器三种类型,三种类型容器特性分别如下:
 

💨【顺序容器】


容器并非排序的,元素的插入位置同元素的值无关。包含 vector、deque、list,具体实现原理如下:

(1)vector 头文件

  • 动态数组。元素在内存连续存放。随机存取任何元素都能在常数时间完成。在尾端增删元素具有较佳的性能。

(2)deque 头文件

  • 双向队列。元素在内存连续存放。随机存取任何元素都能在常数时间完成(仅次于vector)。在两端增删元素具有较佳的性能(大部分情况下是常数时间)

(3)list 头文件

  • 双向链表。元素在内存不连续存放。在任何位置增删元素都能在常数时间完成。不支持随机存取。

💨【关联式容器】

而本期将要介绍的 关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高

元素是排序的;插入任何元素,都按相应的排序规则来确定其位置;在查找时具有非常好的性能;
通常以平衡二叉树的方式实现。包含set、multiset、map、multimap,具体实现原理如下:
(1)set/multiset 头文件

  1. set 即集合。set中不允许相同元素,multiset中允许存在相同元素。

(2)map/multimap 头文件

  1. map与set的不同在于map中存放的元素有且仅有两个成员变量,一个名为first,另一个名为second;
  2. map根据first值对元素从小到大排序,并可快速地根据first来检索元素。

💨【容器适配器】


封装了一些基本的容器,使之具备了新的函数功能,比如把deque封装一下变为一个具有stack功
能的数据结构。这新得到的数据结构就叫适配器。包含stack,queue,priority_queue,具体实现原
理如下:
(1)stack 头文件

  • 栈是项的有限序列,并满足序列中被删除、检索和修改的项只能是最进插入序列的项(栈顶的
  • 项);
  • 后进先出

(2)queue 头文件

  • 队列。插入只可以在尾部进行,删除、检索和修改只允许从头部进行;
  • 先进先出

(3)priority_queue 头文件

  • 优先级队列。内部维持某种有序,然后确保优先级最高的元素总是位于头部。最高优先级元素总是第一个出列

(二)键值对

在C++中,键值对是一种常见的数据结构,它将一个唯一的键与一个值相关联。提供了一种高效的方式来存储和检索数据。该结构中一般只包含两个成员变量keyvalue,key代表键值,value表示与key对应的信息。
 

【场景】

比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该单词,在词典中就可以找到与其对应的中文含义.
 

键值对的定义可以采用不同的数据结构或语法表示,具体取决于所使用的编程语言或数据格式。

以下是一些常见的定义方式:

  • C++关联容器示例:
std::map<std::string, int> myMap;
myMap["apple"] = 10;
myMap["banana"] = 5;
  • JSON格式示例:
{"name": "John","age": 30,"city": "New York"
}
  • Python字典示例:
my_dict = {"key1": "value1", "key2": "value2", "key3": "value3"}
  • JavaScript对象示例:
var myObject = { key1: "value1", key2: "value2", key3: "value3" };

【说明】

  1. 在以上示例中,“key1”、“key2"等都是键,对应的"value1”、"value2"等是对应的值;
  2. 你可以使用键值对来存储、访问和处理各种数据,根据具体编程语言和数据结构的不同,提供了丰富的函数和操作来操作和处理键值对。

而在SGI-STL中关于键值对的定义如下:

template <class T1, class T2>
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair():first(T1()), second(T2()){}pair(const T1& a, const T2& b): first(a), second(b){}};


(三)树形结构的关联式容器

  1. 根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构;
  2. 树型结构的关联式容器主要有四种:map、set、multimap、multiset;
  3. 这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。

下面一依次介绍每一个容器:
 

1、set

 1️⃣基本介绍

  • 官方链接如下:set文档介绍

简单点来说 set是按照一定次序存储元素的容器,且set中的元素不可以重复。具体的大家可以参照文档进行相应的学习。
 

2️⃣set的使用

set的模板参数列表:

 

【说明】

  1. T: set中存放元素的类型,实际在底层存储<value, value>的键值对。
  2. Compare:set中元素默认按照小于来比较
  3. Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理
     

接下来,我们简单的来使用下 set:


void test_set1()
{set<int> s1;s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(2);s1.insert(1);s1.insert(2);set<int>::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";++it1;}cout << endl;
}

输出展示:

 

 

【说明】

  1. 首先,我们可以使用迭代器对其进行操作;
  2. 其次,我们验证了上述所说的  set中的元素不可以重复,可以发现结果自动进行了去重的操作

紧接着,此时我们就会想,既然可以使用迭代器,那么我们就可以知道 范围for 也可以使用:

 


有的小伙伴可能不知道迭代器和范围for的联系,接下来我简单的描述一下:

迭代器 和 范围for循环 都是在 C++ 中用于遍历容器(如数组、向量、映射等)中的元素的工具。它们之间存在联系和互补关系。

  1. 迭代器:迭代器是一个对象,用于遍历容器中的元素序列。通过迭代器,可以逐个访问容器中的元素,并进行增加、删除、修改等操作。C++ 标准库提供了多种类型的迭代器,如 begin()end() 返回的迭代器可以表示容器的起始和结束位置。迭代器可以使用 * 运算符来访问当前位置的值,也可以使用 ++ 运算符来移动到下一个位置。

  2. 范围for循环:范围for循环是一种简洁的语法形式,用于遍历容器中的元素。它可以自动处理迭代器的创建和递增,并以一种更直观的方式对容器中的元素进行访问。范围for循环的语法是 for (element : container),其中 element 是用于存储当前元素的变量,container 是要遍历的容器。在每次循环迭代中,element 会被赋值为容器中的下一个元素,直到遍历完所有元素。

迭代器和范围for循环的联系在于,范围for循环在内部使用迭代器来实现对容器的遍历。范围for循环抽象了迭代器的创建和递增过程,使得代码更加简洁和易读。范围for循环适用于大多数情况下对容器进行遍历,并且不需要修改容器中的元素。而当需要更精细的控制和操作时,迭代器提供了更灵活的功能。


紧接着,在文档中介绍了 set中的元素不能在容器中修改。举例来验证一下:

【说明】

  1. 从上述图片中不难发现在C++的set容器中,元素不允许直接修改;
  2. set是一个有序的集合容器,它通常基于红黑树实现。红黑树是一种平衡二叉搜索树,用于维护元素的有序性。为了保持树的平衡和有序,set 中的元素在插入时按照特定规则被插入到合适的位置,并且不允许直接修改。
  3. 具体而言,当你在set 中插入一个元素时,该元素会被自动插入到正确的位置,以保持集合的有序性。红黑树的平衡性是通过左旋、右旋以及颜色调整等操作来维护的。直接修改元素的值可能导致元素位置不再准确,破坏了红黑树的性质,进而影响整个集合的有序性。
  4. 因此,在set 中,如果你需要修改一个元素,你需要先将该元素从集合中删除,然后再重新插入修改后的值。

【注意】

  • 如果你需要对集合中的元素进行频繁的修改操作,可能 set 并不是最适合的容器选择;
  • 相应地,可以考虑使用 unordered_set容器,它基于哈希表实现,并提供了快速的查找和修改元素的能力;
  • 在 unordered_set中,元素的位置是根据哈希函数计算得到的,而不是通过有序性进行维护,因此允许直接修改元素的值。

接下来,再给大家介绍一下关于 查找元素是否存在的操作。

举例:

void test_set2()
{set<int> s1;s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(2);s1.insert(1);s1.insert(2);int x;while (cin >> x){auto ret = s1.find(x);if (ret != s1.end()){cout << "在" << endl;}else{cout << "不在" << endl;}}}

输出显示:

 

  • 除了上述方法,我们还可以使用 count函数来进行操作。具体如下:
if (s1.count(x))
{cout << "在" << endl;
}
else
{cout << "不在" << endl;
}

输出显示:

 


2、multiset

  • 链接如下:Multiple的文档介绍

 1️⃣ 基本介绍

multiset 对比 set,multiset是按照特定顺序存储元素的容器,其中元素是可以重复

2️⃣ multiset的使用

void test_set3()
{multiset<int> s1;s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(2);s1.insert(1);s1.insert(2);multiset<int>::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";++it1;}cout << endl;
}

输出显示:

 

此时,对于在 set中进行的查找操作,在multiset中该如何表现呢?(因此存在重复的情况)

void test_set3()
{multiset<int> s1;s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(1);s1.insert(2);s1.insert(1);s1.insert(2);s1.insert(1);multiset<int>::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";++it1;}cout << endl;// 多个key,find中序的第一个keyauto ret = s1.find(1);while (ret != s1.end() && *ret == 1){cout << *ret << " ";++ret;}cout << endl;}

输出显示:

 

【说明】

需要注意的是,multiset 中的元素是按键的自然顺序存储的。当存在多个相同的键时,它们按照插入的顺序存储在容器中。使用 find 方法仅返回指向中序遍历的第一个key,而不能一次性找到所有具有相同键的元素。

其次,除了上述的操作之外,multiset 还可以使用 count函数来统计元素出现的次数:

 

对于其他的操作,在这里就不做过多的介绍。大家结合文档我相信各位都可以看懂的!!!


 

3、map

 1️⃣基本介绍

  • 链接如下:map的使用

 

【说明】 

  1.  在正式的学习之前,先要了解在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容;
  2. 键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:

2️⃣ map的使用

【说明】

  1. key: 键值对中key的类型
  2. T: 键值对中value的类型
  3. Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
  4. Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器
  5. 注意:在使用map时,需要包含头文件

接下来,我们简单的来使用下 map:

void test_map1()
{map<string, string> dict;dict.insert(make_pair("insert", "排序"));dict.insert(make_pair("count", "计数"));dict.insert(make_pair("find", "查找"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("swap", "交换"));map<string, string>::iterator dt1 = dict.begin();while (dt1 != dict.end()){cout << (*dt1).first << " ";++dt1;}cout << endl;
}

输出显示:

 【说明】

请注意,指针形式的输出在实际编码中可能不常见。通常,可以直接访问 std::pair 对象的成员变量,并以合适的方式打印出所需的内容。例如,cout << dt1->first << " "; 与 cout << (*dt1).first << " "; 是等效的。

  •  具体如下:

 

 


接下来,带大家看个例子,让大家更加深入的理解:

 【说明】

  • 在 C++ 的map容器中,每个键(key)都是唯一的。当你尝试插入一个已经存在的键时,插入操作会失败;
  • map是一个关联容器,它按照键的顺序对元素进行排序,并且保持唯一键的特性。当你插入一个新的键值对时,map会自动根据键的顺序将其插入到合适的位置,如果已经存在相同的键,则插入失败。


接下来,我给大家讲一下 operator[] 。首先我先用一下这个,让大家直观的感受:

void test_map2()
{string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉", "梨" };map<string, int> countMap;for (auto& e : arr){countMap[e]++;}for (auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}
}

输出结果:

 

接下来,带大家详解这个operator[] :

 

 【解释】

在给定的代码中,this 是一个指向当前对象的指针(或引用),make_pair(k, mapped_type()) 创建一个键为 k,值为默认构造的 mapped_type 类型对象的 std::pair 对象。接下来,通过调用 insert 方法将这个 std::pair 对象插入到容器中,并获取插入结果的迭代器。

然后,通过解引用和成员访问操作符 .second(*((this->insert(make_pair(k, mapped_type ()))).first)).second 表达式从插入结果的迭代器中获取对应元素的值。

其实文档给的有一点太复杂了,在这里我给出简化的版本,供大家参考:

V& operator[](const K& key)
{pair<iterator, bool> ret = insert(make_pair(key, V()));return ret.first->second;
}

接下来,有了上述operator[] 这样的功能,我们就可以使用其进行插入操作了。具体如下:

当我们有这样的代码时: 

dict["left"];			// 插入
dict["right"] = "右边"; // 插入+修改
dict["string"] = "(字符串)"; // 修改
cout << dict["string"] << endl; // 查找
cout << dict["string"] << endl; // 查找

输出展示:

 接下来,我们通过调试看看:

 

【总结】

  • 1. map中的的元素是键值对
  • 2. map中的key是唯一的,并且不能修改
  • 3. 默认按照小于的方式对key进行比较
  • 4. map中的元素如果用迭代器去遍历,可以得到一个有序的序列
  • 5. map的底层为平衡搜索树(红黑树),查找效率比较高$O(log_2 N)$
  • 6. 支持[]操作符,operator[]中实际进行插入查找
     


4、multimap

1️⃣基本介绍

  • 链接如下:multimap的使用

注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以
重复的
 

2️⃣ multimap的使用

multimap中的接口可以参考map,功能都是类似的。

【注意】

  • 1. multimap中的key是可以重复的。
  • 2. multimap中的元素默认将key按照小于来比较
  • 3. multimap中没有重载operator[]操作(同学们可思考下为什么?)。
  • 4. 使用时与map包含的头文件相同:
     

 


(四)在OJ中的使用
 

 1、前k个高频单词

692. 前K个高频单词

class Solution {
public:vector<string> topKFrequent(vector<string>& words, int k) {map<string, int> num;for(auto e : words)num[e]++;//按照单词出现次数的逆序存储单词及其对应的出现次数multimap<int, string, greater<int>> arry;for(auto e : num){arry.insert(make_pair(e.second, e.first));}vector<string> res;auto it = arry.begin();for(int i = 0; i < k; i++){res.push_back(it->second);it++;}return res;}
};

输出结果:

 


2、两个数组的交集

349. 两个数组的交集

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_set<int> set1(nums1.begin(), nums1.end());unordered_set<int> set2(nums2.begin(), nums2.end());vector<int> intersection;for (auto num : set1) {if (set2.find(num) != set2.end()) {intersection.push_back(num);}}return intersection;}
};

输出结果:


总结

 以上便是关于 map和set 的全部知识。感谢大家的观看与支持!!!

 

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

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

相关文章

数据结构——红黑树

文章目录 一.红黑树的定义二.红黑树的插入1.红黑树节点的定义2.红黑树的插入操作3.总结&#xff1a; 三.红黑树与AVL树的比较四.检验手写的红黑树五.源码 一.红黑树的定义 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff…

C++设计模式之访问者模式

C访问者设计模式 文章目录 C访问者设计模式什么是设计模式什么是访问者设计模式该模式有什么优缺点优点缺点 如何使用 什么是设计模式 设计模式是一种通用的解决方案&#xff0c;用于解决特定的一类问题。它是一种经过验证的代码组织方式&#xff0c;可以帮助开发人员更快地实…

STM32 DHT11

DHT11 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。 使用单总线通信 该传感器包括一个电容式感湿元件和一个NTC测温元件&#xff0c;并于一个高性能8位单片机相连&#xff08;模数转换&#xff09;。 DHT11引脚说明 开漏模式下没有输出高电平的能…

Cilium系列-14-Cilium NetworkPolicy 简介

系列文章 Cilium 系列文章 前言 今天我们进入 Cilium 安全相关主题, 介绍 Kubernetes 网络策略以及 CiliumNetworkPolicies 额外支持的内容。 网络策略(NetworkPolicy)的类型 默认情况下&#xff0c;Kubernetes 集群中的所有 pod 都可被其他 pod 和网络端点访问。 网络策…

【并发专题】单例模式的线程安全(进阶理解篇)

目录 背景前置知识类加载运行全过程 单例模式的实现方式一、饿汉式基本介绍源码分析 二、懒汉式基本介绍源码分析改进 三、懒汉式单例终极解决方案&#xff08;静态内部类&#xff09;&#xff08;推荐使用方案&#xff09;基本介绍源码分析 感谢 背景 最近学习了JVM之后&…

解决SVN或GIT忽略提交文件的问题

背景 使用IDEA 的SVN插件提交文件是总是会提交一些不需要提交的文件; 我们可以通过一些简单设置忽略这些文件。 git 在项目根目录新建文本文件&#xff0c;修改后缀为.gitignore 文件中添加内容 *.iml .project .gradle/ .idea/ target/ build/ .vscode/ .settings/ .facto…

Python 开发工具 Pycharm —— 使用技巧Lv.2

pydoc是python自带的一个文档生成工具&#xff0c;使用pydoc可以很方便的查看类和方法结构 本文主要介绍&#xff1a;1.查看文档的方法、2.html文档说明、3.注释方法、 一、查看文档的方法 **方法1&#xff1a;**启动本地服务&#xff0c;在web上查看文档 命令【python3 -m…

Mac系统下使用远程桌面连接Windows系统

一、远程桌面工具 Microsoft Remote Desktop 二、下载地址 https://go.microsoft.com/fwlink/?linkid868963 三、下载并安装 四、添加远程PC PC name:云服务器IP。 User account: 添加系统用户 PC name&#xff1a;远程桌面 IP 地址User account&#xff1a;可以选择是…

【iOS】多线程 锁问题总结

文章目录 前言1. 你理解的多线程优点缺点 2. atomic 和 nonatomic 的区别及其作用3. GCD的队列类型 - 三种队列类型4. GCD的死锁问题线程死锁的四个必要条件 5. 多线程之间的区别和联系6. 进程和线程&#xff1f;进程间的通信方式线程间的通信方式 6. iOS的线程安全手段如何保证…

Matlab修改文本编码格式为UTF-8

一、修改文本编码格式 Matlab默认使用GBK编码格式&#xff0c;当代码中有中文注释时&#xff0c;注释显示乱码。 修改配置文件(安装目录下的bin目录有个lcdata.xml)&#xff0c;如下&#xff1a; 1. 删除 2. 修改 < encoding name”UTF-8”> < encoding_alias nam…

postgresql 使用之 存储架构 触摸真实数据的存储结构以及组织形式,存入数据库的数据原来在这里

存储架构 ​专栏内容&#xff1a; postgresql内核源码分析 手写数据库toadb 并发编程 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 概述 postgresql 数据库服务运行时&#xff0c;数据在磁…

kafka-保证数据不重复-生产者开启幂等性和事务的作用?

1. 生产者开启幂等性为什么能去重&#xff1f; 1.1 场景 适用于消息在写入到服务器日志后&#xff0c;由于网络故障&#xff0c;生产者没有及时收到服务端的ACK消息&#xff0c;生产者误以为消息没有持久化到服务端&#xff0c;导致生产者重复发送该消息&#xff0c;造成了消…

常见监控网络链路和网络设备的方法

网络监控主要包括网络链路监控和网络设备监控&#xff0c;通常系统运维人员会比较关注。 一、网络链路监控 网络链路监控主要包含三个部分&#xff0c;网络连通性、网络质量、网络流量。 连通性和质量的监控手段非常简单&#xff0c;就是在链路一侧部署探针&#xff0c;去探…

二、点亮LED灯

1. 原理 想要让一个LED灯亮&#xff0c;那么就要给其供电&#xff0c;使得有电流通过 与小时候玩的一节7号电池和普通小灯泡是一个道理 2. 查看ESP32开发板电路图 通过查看电路图&#xff0c;来确定开发板上的LED等的与MCU的引脚链接方式 查看上图我们知道&#xff0c;GPIO2这…

Mac应用程序无法打开或文件损坏的处理方法

1. 打开系统偏好设置界面&#xff0c;进入安全性与隐私&#xff0c;如下图所示&#xff1a; 2. 点按左下角的锁头图标&#xff0c;解锁更改权限 3. 将允许从以下位置下载的应用&#xff0c;更改为 “ 任何来源 ” &#xff0c;然后再打开应用即可 有朋友就说了&#xff0c;我这…

Ubuntu 23.04 作为系统盘的体验和使用感受

1.为啥主系统装了Ubuntu 由于公司发电脑了&#xff0c;我自己也有一台台式电脑&#xff0c;然后也想去折腾一下Ubuntu&#xff0c;就把自己的笔记本装成Ubuntu系统了&#xff0c; 我使用的是23.04的桌面版&#xff0c;带图形化界面的。我准备换回Windows 11了&#xff08;因为…

06 Ubuntu22.04上的miniconda3安装、深度学习常用环境配置

下载脚本 我依然是在清华镜像当中寻找的脚本。这里找脚本真的十分方便&#xff0c;我十分推荐。 wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh 下载十分快速&#xff0c;10秒解决问题 运行miniconda3安装脚本 赋予执…

Java循环:探索迭代的世界

文章目录 1. for循环2. while循环3. do-while循环总结 循环是编程中的重要概念&#xff0c;它允许我们重复执行特定的代码块&#xff0c;帮助我们简化复杂的任务和提高代码的效率。在Java中&#xff0c;循环有多种形式&#xff0c;包括for循环、while循环和do-while循环。本篇博…

PHP-简单项目引起的大麻烦--【白嫖项目】

强撸项目系列总目录在000集 PHP要怎么学–【思维导图知识范围】 文章目录 本系列校训本项目使用技术 首页小插曲小插曲完了么&#xff1f;必要的项目知识PHPThinkPHPThinkPHP的MVCThinkTemplateThinkPHP 6和ThinkPHP 5 phpStudy 设置导数据库展示页面数据库表结构项目目录如图…

Java on Azure Tooling 6月更新|标准消费和专用计划及本地存储账户(Azurite)支持

作者&#xff1a;Jialuo Gan - Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎阅读 Java on Azure 工具的六月更新。在本次更新中&#xff0c;我们将介绍 Azure Spring Apps 标准消费和专用计划支持以及本地存储账户&…