【C++进阶篇】C++容器完全指南:掌握set和map的使用,提升编码效率
C++容器的实践与应用:轻松掌握set、map与multimap的区别与用法
- 一. 序列式容器与关联式容器
- 1.1 序列式容器 (Sequential Containers)
- 1.2 关联式容器 (Associative Containers)
- 二. set系列使用
- 2.1 set的构造和迭代器
- 2.2 set的增删查
- 2.2.1 插入
- 2.2.2 查找
- 2.2.3 删除
- 2.3 multiset和set的差异
- 三. map系列使用
- 3.1 pair类
- 3.1.1 定义与创建
- 3.1.2 访问元素
- 3.2 map构造
- 3.3 map增删查
- 3.3.1 插入
- 2.2.2 查找
- 2.2.3 删除
- 3.4 map[]功能(重点)
- 3.4.1 基本功能
- 3.4.2 返回值类型
- 3.4.3 自动插入特性
- 3.5 multimap和map的差异
- 四. 最后
在C++中,容器是存储和操作数据的核心工具。序列式容器(如vector、list)通过线性顺序存储数据,而关联式容器(如set、map)则通过键值对存储数据,允许更高效的查找、插入和删除。set是一个存储唯一元素的容器,内部自动排序,底层通常使用红黑树实现。它支持高效的查找和元素去重。map是存储键值对的容器,每个键都是唯一的,值可以重复,同样基于红黑树实现,提供快速的键值对查找。在需要快速检索、插入或删除元素时,set和map是非常实用的选择。
一. 序列式容器与关联式容器
1.1 序列式容器 (Sequential Containers)
序列式容器按照元素的插入顺序进行存储,它们提供了对元素的线性访问。序列式容器的元素是有顺序的,可以通过下标或迭代器来访问。常见的序列式容器包括:
-
vector:动态数组,支持快速的随机访问。适用于频繁访问元素,但在中间插入或删除元素时性能较差。
-
deque:双端队列,支持在两端快速插入和删除元素,但相比 vector,在访问和修改元素时稍慢。
-
list:双向链表,支持在任意位置快速插入和删除元素,但不支持随机访问。
-
array:固定大小的数组,支持快速随机访问,但在大小固定时使用。
-
forward_list:单向链表,比 list 更节省内存,但只支持向前遍历。
1.2 关联式容器 (Associative Containers)
关联式容器是基于键值对的容器,每个元素由键和值组成,并且通过键进行访问。它们通常提供基于键的排序和查找功能,能够高效地查找、插入和删除元素。常见的关联式容器包括:
-
set:存储唯一元素的集合,自动排序。可以高效地判断元素是否存在。
-
map:存储键值对,其中每个键都是唯一的,值可以重复。自动按照键排序。
-
multiset:与 set 类似,但允许存储重复的元素。
-
multimap:与 map 类似,但允许存储重复的键。
声明:本篇文章重点介绍关联式容器中的set,map
二. set系列使用
set的底层是用红黑树实现的,增删查效率是 O(logN),迭代器的遍历是中序,所以是有序的。
2.1 set的构造和迭代器
set的迭代器是双向迭代器,遍历默认是升序的,因为底层说到底还是二叉搜索树,所以迭代器(const和非const版本迭代器)都不支持修改数据,会破坏二叉搜索树的结构。
构造类型 | 原型 | 功能 |
---|---|---|
无参默认构造 | explicit set (const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type()); | 构造一个指定类型T的对象 |
迭代器区间构造 | template set(InputIterator first, InputIterator last,const key_compare & comp = key_compare(),const allocator_type & = allocator_type()); | 使用迭代器区间初始化对象 |
初始化列表构造 | set(initializer_list<value_type> il,const key_compare & comp = key_compare(),const allocator_type & alloc = allocator_type()); | 使用初始化列表构造对象 |
拷贝构造 | set (const set& x); | 使用拷贝构造对象 |
迭代器 | 原型 | 功能 |
正向迭代器 | iterator begin();iterator end() | 正向遍历容器中的数据 |
反向迭代器 | reverse_iterator rbegin();reverse_iterator rend(); | 反向遍历容器中的数据 |
下面将给出一个整合代码演示上述的功能:
- 示例代码:
#include<iostream>
#include<set>
using namespace std;int main()
{//无参默认构造set<int> s1;cout << "修改前s1: ";for (auto ch : s1){cout <<"原:s1 " << ch;}cout << endl;//迭代器区间构造set<int> s2({ 1,2,3,4,5,6,7,8,9,10 });//initializer 列表构造//set<int> s1(s2.begin(), s2.end());错误写法,s1重定义//使用赋值,或者直接插入//s1.insert(s2.begin(),s2.end())s1 = set<int>(s2.begin(), s2.end());//创建临时对象,进行赋值cout << "修改后s1:";for (auto ch : s1){cout << ch << " ";}cout << endl;//拷贝构造set<int> s3(s1);cout << "s3: ";for (auto ch : s3){cout <<ch << " ";}cout << endl;// 正确的反向遍历cout << "Reverse traversal of s3: ";for (auto rit = s3.rbegin(); rit != s3.rend(); ++rit) {cout << *rit << " ";}cout << endl;return 0;
}
2.2 set的增删查
2.2.1 插入
类型 | 原型 | 功能 |
---|---|---|
单个插入 | pair<iterator,bool> insert (const value_type& val); | 插入单个数据,插入已经存在插入失败 |
列表插入 | insert (initializer_list<value_type> il); | 使用初始化列表插入元素 |
迭代器区间插入 | template void insert(InputIterator first, InputIterator last); | 使用迭代器区间插入元素 |
下面将给出一个整合代码演示上述的功能:
- 示例代码:
#include<iostream>
#include<set>
using namespace std;int main()
{int a = 10;set<int> s;s.insert(a);//插入单个数据for (auto ch : s){cout << ch;}cout << endl;s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入for (auto ch : s){cout << ch<<" ";}cout << endl;set<int> s3({ 10,20,30,40,50,60,70,80,90,100 });s.insert(s3.begin(), s3.end());//迭代器区间插入数据for (auto ch : s){cout << ch << " ";}cout << endl;return 0;
}
2.2.2 查找
类型 | 原型 | 功能 |
---|---|---|
查找单个元素 | iterator find (const value_type& val); | 查找val,返回val所在的迭代器,没有找到返回end() |
查找每个元素的总出现个数 | size_type count (const value_type& val) const; | 查找val,返回Val的个数 |
下面将给出一个整合代码演示上述的功能:
- 示例代码:
#include<iostream>
#include<set>
using namespace std;int main()
{set<int> s;s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入for (auto ch : s){cout << ch<<" ";}cout << endl;auto it = s.find(6);//存在返回所在迭代器cout << *it << endl;it = s.find(10);//不存在不可进行解引用//cout << *it << endl;error程序会终止int ret = s.count(6);cout << ret << endl;//查找6出现的总个数return 0;
}
2.2.3 删除
类型 | 原型 | 功能 |
---|---|---|
删除单个元素 | size_type erase (const value_type& val); | 删除val,val不存在返回0,存在返回1 |
删除迭代器位置 | iterator erase (const_iterator position); | 删除⼀个迭代器位置的值 |
删除迭代器区间 | iterator erase (const_iterator first, const_iterator last) | 删除⼀段迭代器区间的值 |
下面将给出一个整合代码演示上述的功能:
- 示例代码:
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
#include<set>
using namespace std;int main()
{set<int> s;s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入cout << "删除前: ";for (auto ch : s){cout << ch<<" ";}cout << endl;cout << "删除5后: ";s.erase(5);//删除单个值for (auto ch : s){cout << ch << " ";}cout << endl;cout << "删除8后: ";auto it = s.find(8);s.erase(it);//删除迭代器位置的值for (auto ch : s){cout << ch << " ";}cout << endl;cout << "全部删除后: ";s.erase(s.begin(), s.end());//删除迭代器区间区间的值,等效于s.clear()for (auto ch : s){cout << ch << " ";}cout << endl;return 0;
}
补充:
// 返回⼤于等val位置的迭代器
- iterator lower_bound (const value_type& val) const;
// 返回⼤于val位置的迭代器
- iterator upper_bound (const value_type& val) const;
2.3 multiset和set的差异
multiset和set的使⽤基本完全类似,主要区别点在于multiset⽀持值冗余,说白就是允许插入相同的值。
下面主要来看insert/find/count/erase都围绕着⽀持值冗余有所差异,示例代码:
```cpp
#include<iostream>
#include<set>
using namespace std;
int main()
{// 相⽐set不同的是,multiset是排序,但是不去重multiset<int> s = { 4,2,7,2,4,8,4,5,4,9 };auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 相⽐set不同的是,x可能会存在多个,find查找中序的第⼀个int x;cin >> x;auto pos = s.find(x);while (pos != s.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;// 相⽐set不同的是,count会返回x的实际个数cout << s.count(x) << endl;// 相⽐set不同的是,erase给值时会删除所有的xs.erase(x);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}
三. map系列使用
map的底层是红黑树,key/value结构场景,也是有序的。
3.1 pair类
在C++中,pair 是标准模板库(STL)提供的一个模板类,用于将两个可能不同类型的对象组合成一个单一单元。
3.1.1 定义与创建
#include // 包含pair的头文件
// 创建pair的几种方式
std::pair<int, double> p1; // 默认构造,两个元素被值初始化
std::pair<int, double> p2(1, 3.14); // 直接初始化 std::pair<int,
double> p3 = {2, 2.718}; // 列表初始化(C++11起) auto p4 =
std::make_pair(3, 1.618); // 使用make_pair辅助函数
3.1.2 访问元素
int first_element = p2.first; // 访问第一个元素(int类型)
double second_element = p2.second; // 访问第二个元素(double类型)
结论:pair 是C++中处理简单二元组合的高效工具,在需要临时组合两个相关值时非常有用。对于更复杂的数据结构,建议使用 struct 或 class 来提高代码可读性。
3.2 map构造
map的迭代器是双向迭代器,遍历默认是升序的,因为底层说到底还是二叉搜索树,所以迭代器(const和非const版本迭代器)都不支持修改数据,会破坏二叉搜索树的结构。
构造类型 | 原型 | 功能 |
---|---|---|
无参默认构造 | explicit map(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type()); | 构造一个指定类型T的对象 |
迭代器区间构造 | template map(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type()); | 使用迭代器区间初始化对象 |
初始化列表构造 | map(initializer_list<value_type> il,const key_compare & comp = key_compare(),const allocator_type & alloc = allocator_type()); | 使用初始化列表构造对象 |
拷贝构造 | map (const map& x); | 使用拷贝构造对象 |
迭代器 | 原型 | 功能 |
正向迭代器 | iterator begin();iterator end(); | 正向遍历容器中的数据 |
反向迭代器 | reverse_iterator rbegin();reverse_iterator rend(); | 反向遍历容器中的数据 |
下面将给出一个整合代码演示上述的功能:
- 示例代码:
#include<iostream>
#include<map>
using namespace std;int main()
{//无参默认构造map<string, string> t1;for (auto entry : t1){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//初始化列表构造map<string, string> t2({{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//迭代器区间构造map<string, string> t3(t2.begin(), t2.end());for (auto entry : t3){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//拷贝构造map<string, string> t4(t2);for (auto entry : t4){cout << entry.first << " -> " << entry.second << endl;}cout << endl;//正向迭代器遍历auto it = t4.begin();while (it != t4.end()){cout << it->first << " " << it->second << endl;++it;}cout << endl;//反向迭代器遍历for (auto it = t4.rbegin(); it != t4.rend(); it++){cout << it->first << " " << it->second << endl;}return 0;
}
3.3 map增删查
3.3.1 插入
类型 | 原型 | 功能 |
---|---|---|
单个插入 | pair<iterator,bool> insert (const value_type& val); | 单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败 |
列表插入 | void insert (initializer_list<value_type> il); | 列表插⼊,已经在容器中存在的值不会插⼊ |
迭代器区间插入 | template void insert(InputIterator first, InputIterator last); | 使用迭代器区间插入元素 |
下面将给出一个整合代码演示上述的功能:
- 示例代码:
#include<iostream>
#include<map>
using namespace std;int main()
{pair<string, string> s("insert", "插入");map<string, string> t1;t1.insert(s);//插入单个元素cout << "t1: ";for (auto entry : t1){cout << entry.first << " -> " << entry.second << endl;}cout << endl;map<string, string> t2;t2.insert({ { "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入cout << "t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;map<string, string> t3;t3.insert(t2.begin(), t2.end());//迭代器区间插入cout << "t3: ";for (auto entry : t3){cout << entry.first << " -> " << entry.second << endl;}cout << endl;return 0;
}
2.2.2 查找
类型 | 原型 | 功能 |
---|---|---|
查找单个元素 | iterator find (const value_type& val); | 查找val,返回val所在的迭代器,没有找到返回end() |
查找每个元素的总出现个数 | size_type count (const value_type& val) const; | 查找val,返回Val的个数 |
下面将给出一个整合代码演示上述的功能:
- 示例代码:
#include<iostream>
#include<map>
using namespace std;int main()
{map<string, string> t2;t2.insert({ { "apple", "苹果" },{ "apple", "苹果" },{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入cout << "t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}auto it = t2.find("apple");//返回apple位置所在的迭代器cout << it->first << " " << it->second << endl;int ret = t2.count("apple");//查找apple出现的总次数cout << ret << endl;return 0;
}
2.2.3 删除
类型 | 原型 | 功能 |
---|---|---|
删除单个元素 | size_type erase (const value_type& val); | 删除val,val不存在返回0,存在返回1 |
删除迭代器位置 | iterator erase (const_iterator position); | 删除⼀个迭代器位置的值 |
删除迭代器区间 | iterator erase (const_iterator first, const_iterator last) | 删除⼀段迭代器区间的值 |
示例代码:
#include<iostream>
#include<map>
using namespace std;int main()
{map<string, string> t2;t2.insert({ { "apple", "苹果" },{ "apple", "苹果" },{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入cout << "删除前t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;t2.erase("apple");//删除指定元素值cout << "前t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;auto it = t2.find("orange");t2.erase(it);//删除迭代器位置的值cout << "中t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}cout << endl;t2.erase(t2.begin(), t2.end());//删除迭代器区间的值cout << "后t2: ";for (auto entry : t2){cout << entry.first << " -> " << entry.second << endl;}return 0;
}
3.4 map[]功能(重点)
3.4.1 基本功能
- 访问元素:如果键存在于map中,operator[]会返回该键对应的值的引用。
- 修改元素:通过返回的引用,可以直接修改该键对应的值。
- 插入元素:如果键不存在于map中,operator[]会插入一个新的键值对,其中键是给定的键,值是值类型的默认构造值(对于内置类型如int、string等,默认构造值通常是0或空字符串;对于自定义类型,则是其默认构造函数创建的对象)。
3.4.2 返回值类型
operator[]返回的是值的引用(value_type&),这允许对值进行直接修改。
3.4.3 自动插入特性
当使用operator[]访问一个不存在的键时,map会自动插入一个新的键值对。
新插入的键的值部分是其值类型的默认构造值。
- 使用实例:
#include<iostream>
#include<map>
#include<string>
using namespace std;int main() {map<string, int> wordCount;// 访问并修改现有元素wordCount["apple"] = 10; // 插入或修改键为"apple"的元素cout << "apple: " << wordCount["apple"] << endl; // 输出: apple: 10// 访问不存在的键,自动插入新元素cout << "banana: " << wordCount["banana"] << endl; // 输出: banana: 0(因为int的默认构造值是0)// 修改自动插入的元素wordCount["banana"] += 5;cout << "banana: " << wordCount["banana"] << endl; // 输出: banana: 5// 使用at()方法访问元素(需要确保键存在)try {cout << "orange: " << wordCount.at("orange") << endl;} catch (const out_of_range& e) {cout << "orange: " << e.what() << endl; // 输出: orange: map::at: key not found}return 0;
}
3.5 multimap和map的差异
multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么
insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,
- 示例代码:
#include <iostream>
#include <map>
#include <string>using namespace std;int main() {// 创建multimap并插入数据multimap<string, int> scores = {{"Alice", 90},{"Bob", 85},{"Alice", 95}, // 允许重复的key{"Charlie", 88}};// 1. 查找操作(返回第一个匹配项)auto it = scores.find("Alice");if (it != scores.end()) {cout << "找到Alice的第一个分数: " << it->second << endl; // 输出90}// 2. 计数操作(统计重复key的数量)int count = scores.count("Alice");cout << "Alice出现的次数: " << count << endl; // 输出2// 3. 范围查找(获取所有匹配项)cout << "所有Alice的分数: ";auto range = scores.equal_range("Alice");for (auto itr = range.first; itr != range.second; ++itr) {cout << itr->second << " "; // 输出90 95}cout << endl;// 4. 删除操作(删除所有匹配项)scores.erase("Alice");cout << "删除Alice后剩余元素数量: " << scores.size() << endl; // 输出2(Bob和Charlie)// 5. 尝试使用[]操作符(会编译失败)// scores["David"] = 78; // 错误:multimap不支持[]操作符return 0;
}
通过这个示例可以看出,multimap在处理需要多个相同key的场景时比map更灵活,但相应地也失去了一些特性(如[]操作符的直接访问能力)。在实际开发中,应根据是否需要key唯一性来选择合适的数据结构。
四. 最后
本文详述了C++中关联式容器set、multiset、map、multimap的用法,涵盖构造、迭代器、增删查等操作。set自动排序去重,multiset允许重复;map存储键值对,multimap支持键冗余。重点解析了map的[]操作符自动插入特性及multimap的范围查找。通过代码示例展示了各容器的核心功能与应用场景,是学习C++标准库关联容器的实用指南。
相关文章:
【C++进阶篇】C++容器完全指南:掌握set和map的使用,提升编码效率
C容器的实践与应用:轻松掌握set、map与multimap的区别与用法 一. 序列式容器与关联式容器1.1 序列式容器 (Sequential Containers)1.2 关联式容器 (Associative Containers) 二. set系列使用2.1 set的构造和迭代器2.2 set的增删查2.2.1 插入2.2.2 查找2.2.3 删除 2.…...
吴恩达机器学习(1)——机器学习算法分类
1、机器学习算法 1、监督学习 在实际应用中最为常见的快速进度结果 2、非监督学习 2、监督学习(Supervised Learning) 2.1、回归算法 [!note] 监督学习 是指学习从 x -> y 或者从输入到输出映射的算法 监督学习的关键特征是你给学习算法提供学习…...
我的创作纪念日——512天
2023 年 12 月 19 日,我撰写了第 1 篇记录型博客《数据结构课程设计——报数问题》,这是我记录一段实践经验的开始。 回望那时的自己,还很稚嫩,刚刚迈入计算机的大门不久,一切都显得新鲜而充满挑战。今天是我成为创作者…...
SpringBoot快速上手
1.Maven Maven是项目管理工具,通过pom.xml文件来获取jar包,而不用手动去添加jar包 引入依赖之后需要刷新maven,以下这两个地方都可以 中央仓库 : Central Repository: Maven Repository: Central 2.Spring Boot 2.1创建项目…...
自动化:批量文件重命名
自动化:批量文件重命名 1、前言 2、效果图 3、源码 一、前言 今天来分享一款好玩的自动化脚:批量文件重命名 有时候呢,你的文件被下载下来文件名都是乱七八糟毫无规律,但是当时你下载的时候没办法重名或者你又不想另存为重新重…...
低延迟与高性能的技术优势解析:SmartPlayer VS VLC Media Player
在实时视频流的应用中,RTSP(Real-Time Streaming Protocol)播放器扮演着至关重要的角色,尤其是在视频监控、远程医疗、直播等高实时性需求的场景中。随着行业需求的不断升级,对播放器的低延迟、稳定性、兼容性等方面的…...
java中的Servlet2.x详解
一、Servlet 2.x 版本演进与核心特性 Servlet 2.x 是 Java Web 开发中承上启下的重要版本系列,主要包括 Servlet 2.4 和 Servlet 2.5 两个子版本。以下是其核心特性与改进: Servlet 2.4(2003年发布) XML Schema 支持:…...
大模型deepseek如何助力数据安全管理
敏感数据识别与处理 精准定位敏感信息 :运用多模态识别引擎技术,快速扫描上传文件与输入内容,精准识别身份证号、银行卡号、商业合同关键信息等各类敏感数据,并支持金融、医疗等行业定制化规则库,满足不同行业的特殊需…...
【linux驱动】【设备树】按键设备树讲解
设备树你添加电源键示例。 / {gpio-keys {compatible = "gpio-keys";#address-cells = <1>;#size-cells = <0>;button@1 {label = "Power Button";linux,code = <KEY_POWER>; // 按键编码,定义在include/uapi/linux/input-event-code…...
Vibe Coding:编程中的氛围与效率的艺术
引言 在软件开发的世界里,我们常常关注语言特性、框架选择和算法效率,却较少讨论一个同样重要的因素——编程时的"氛围"(vibe)。Vibe Coding是一种关注开发者心理状态、工作环境和整体"感觉"的编程方法论。它…...
算法岗实习八股整理——深度学习篇(不断更新中)
目录 激活函数特征典型例子sigmod函数tanh函数补充:零中心化输出优势非线性特性如何提升神经网络表现 激活函数 特征 非线性:激活函数满足非线性时,才不会被单层网络替代,神经网络才有意义可微性:优化器大多数是用梯…...
Java IO及Netty框架学习小结
Netty netty官网: Netty 什么是Netty? Netty 是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。Netty 是一个 NIO 客户端服务器框架,可以快速轻松地开发网络应用程序(例如协议服务器和客…...
理想AI Talk第二季-重点信息总结
一、TL;DR 理想为什么要做自己的基模:座舱家庭等特殊VLM场景,deepseek/openai没有解决理想的基模参数量:服务端-300B,VLencoder-32B/3.6B,日常工作使用-300B,VLA-4B为什么自动驾驶可以达成&…...
软件架构之-论软件系统架构评估以及应用
论软件系统架构评估以及应用 摘要正文 摘要 2023年2月,本人所在集团公司承接了长三角地区某省渔船图纸电子化审查系统项目开发,该项目旨在为长三角地区渔船建造设计院,以及渔船图纸审查机构提供一个便捷化的服务平台。在此项目中,…...
Java面试实战:从Spring Boot到分布式缓存的深度探索
Java面试实战:从Spring Boot到分布式缓存的深度探索 场景介绍 在一家著名的互联网大厂,面试官老王正对求职者“水货程序员”明哥进行Java技术面试。明哥带着一点紧张和自信,迎接这场技术“拷问”。 第一轮:基础问题 老王&#…...
2025年全国青少年信息素养大赛C++小学全年级初赛试题
一、单选题 1、在C中,表示逻辑运算符 "或" 的是?( )(5 分) A.|| B.& C. D. 解析:||是或者, &&是并且 2、…...
React中巧妙使用异步组件Suspense优化页面性能。
文章目录 前言一、为什么需要异步组件?1. 性能瓶颈分析2. 异步组件的价值 二、核心实现方式1. React.lazy Suspense(官方推荐)2. 路由级代码分割(React Router v6) 总结 前言 在 React 应用中,随着功能复…...
nginx相关面试题30道
一、基础概念与核心特性 1. 什么是 Nginx?它的主要用途有哪些? 答案: Nginx 是一款高性能的开源 Web 服务器、反向代理服务器及负载均衡器,基于事件驱动的异步非阻塞架构,擅长处理高并发场景。 主要用途:…...
java中的Servlet1.x详解
Servlet 1.x 是 Java Web 开发的早期规范,为后续版本奠定了基础。以下是其核心特性、使用方式及与现代版本的对比分析: 一、Servlet 1.x 的核心特性 基础接口与实现 Servlet 1.x 的核心是 javax.servlet.Servlet 接口,开发者必须直接实现其五…...
给大模型“贴膏药”:LoRA微调原理说明书
一、前言:当AI模型开始“叛逆” 某天,我决定教deepseek说方言。 第一次尝试(传统微调): 我:给deepseek灌了100G东北小品数据集,训练三天三夜。结果:AI确实会喊“老铁666”了…但英…...
【数字电路】第七章 脉冲波形的产生与整形电路
一、脉冲波形的产生与整形电路概述 1.矩形脉冲的获得方法 2.矩形脉冲的主要参数 3.本章所涉及的电路 4.稳态与暂稳态 电路的暂稳态实际上是通过RC电路的充放电来实现的。 5.TTL电路输入等效电路 6.TTL电路的输出等效电路 7.CMOS电路的输入等效电路 8.CMOS电路的输出等效电路 …...
React Flow 边的基础知识与示例:从基本属性到代码实例详解
本文为《React Agent:从零开始构建 AI 智能体》专栏系列文章。 专栏地址:https://blog.csdn.net/suiyingy/category_12933485.html。项目地址:https://gitee.com/fgai/react-agent(含完整代码示例与实战源)。完整介绍…...
DB-MongoDB-00002--Workload Generator for MongoDB
## DB-MongoDB-00002–Workload Generator for MongoDB 1、介绍 Workload Generator for MongoDB was designed to help MongoDB users effortlessly generate data and simulate workloads for both sharded and non-sharded clusters. The generated workloads include s…...
buck变换器的simulink/matlab仿真和python参数设计
什么是Buck电路? BUCK电路是一种降压斩波器,降压变换器输出电压平均值Uo总是小于输出电压UD。通常电感中的电流是否连续,取决于开关频率、滤波电感L和电容C的数值。BUCK也是DC-DC基本拓扑,或者称为电路结构,是最基本的DC-DC电路…...
谷歌地球引擎GEE将多个遥感影像作为多个波段合并成一张图像并下载的方法
本文介绍在谷歌地球引擎(Google Earth Engine,GEE)中,下载多年的逐日的ERA5土壤湿度数据,并在下载时,将每年同月份内的每一天的图像作为一个波段加以合并的方法。 在之前的文章GEE谷歌地球引擎批量下载逐日…...
Debezium快照事件监听器系统设计
Debezium快照事件监听器系统设计 1. 系统概述 1.1 设计目标 为 Debezium 的快照过程提供可扩展的事件监听机制允许外部系统在快照过程中执行自定义逻辑提供线程安全的事件分发机制确保监听器的异常不会影响主快照流程1.2 核心功能 表快照开始事件监听表快照完成事件监听行数据…...
选择之困:如何挑选合适的 Python 环境与工具——以 Google Colaboratory 为例
引言:选择之困与 Python 的多样性 在过去的十年中,Python 编程语言以其简洁的语法、强大的功能和广泛的适用性迅速崛起,成为全球最受欢迎的编程语言之一。从数据科学到 Web 开发,从自动化脚本到人工智能,Python 无处不在。然而,这种多样性和快速发展也带来了一个显著的问…...
基于Java+MySQL+Servlet的留言系统开发全解析
本系统基于Java Web技术栈开发,采用前后端分离架构,后端通过Servlet实现业务逻辑,前端使用HTML/CSS/JavaScript构建交互界面。本文将详细解析系统设计思路、技术实现与核心代码,助您快速掌握留言系统开发精髓。 一、项目简介 本留…...
实操分享java应用容器化,使用docker作为容器工具
### 一. 目的 将现有的java应用容器化,使用docker作为容器工具。 ### 二. 配置 #### 1. Java应用中的配置 ##### a. Java子项目中的pom文件配置 ```xml <build> <plugins> <plugin> <groupId>org.spring…...
李臻20242817_安全文件传输系统项目报告_第12周
安全文件传输系统项目报告(第 9 周) 1. 代码链接 Gitee 仓库地址:https://gitee.com/li-zhen1215/homework/tree/master/Secure-file 代码结构说明: project-root/├── src/ # 源代码目录│ ├── main.c # 主程序入口│ ├…...
19-I2C库函数
一、IIC配置流程 IIC配置流程需要添加的库函数:stm32f4xx_i2c.c 1、理解电路原理图 SCL --- PB8 SDA -- PB9 使用I2C1 2、配置I2C库函数的步骤 (1)使能GPIOB组时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);(2…...
minicom串口调试助手
sudo apt-get install minicom 配置 sudo minicom -s 然后用方向键向下移动到“Serial port setup”,回车 按键盘“A”把串口的映射文件名输入。 按键盘“E”可以修改波特率 按键盘“F”把硬件流关闭,否则minicom可能无法接收键盘输入。 配置好后&…...
扫描件交叉合并PDF免费软件 拖拽即合并 + 自动对齐页码 档案整合更轻松
各位办公小能手们!我跟你们说啊,今天要给你们介绍个超厉害的工具,叫PDFCrossMerge。这玩意儿就像一个神奇的文档小魔法师,专门搞PDF扫描件交叉合并的事儿,能解决单面扫描文件正反面页码顺序的大难题。 先说说它的核心…...
atcoder C - ~
https://atcoder.jp/contests/abc406/tasks/abc406_c 题目简述: 给定一个序列p,让你求出p的所有子序列中波浪形序列的个数 波浪形序列的定义:1:长度>4;2:仅存在一个波峰和波谷;3࿱…...
PCB设计实践(十八)PCB设计铜厚选择及分层设计深度解析
PCB铜箔厚度作为电路板设计的核心参数之一,直接影响电路性能、可靠性及成本。本文将从铜厚选择的六大核心要素、多层板分层设计的策略、制造工艺的耦合关系三大维度,系统性解析PCB铜厚设计的工程方法论,并结合典型应用场景提供决策框架。 一、…...
React 19中如何向Vue那样自定义状态和方法暴露给父组件。
文章目录 前言一、什么是 useImperativeHandle?1.1 为什么需要 useImperativeHandle?1.2 基本语法 二、useImperativeHandle 的常见用法3.1 暴露自定义方法3.2子组件封装的弹窗关闭方法暴露给外部 注意点:总结 前言 在 React 的函数组件中&a…...
【Linux高级全栈开发】2.1.2 事件驱动reactor的原理与实现
【Linux高级全栈开发】2.1.2 事件驱动reactor的原理与实现 高性能网络学习目录 基础内容(两周完成): 2.1网络编程 2.1.1多路复用select/poll/epoll2.1.2事件驱动reactor2.1.3http服务器的实现 2.2网络原理 百万并发PosixAPIQUIC 2.3协程库…...
1.5 MouseDown,MouseUp,LostMouseCapture的先后顺序
本文目标是实现如下功能: 按下一个按钮后置位某变量;鼠标松开后复位某个变量? 看似简单,但是一般来说会存在如下两种现象: 鼠标移出按钮:默认会丢失鼠标事件跟踪,即MouseLeftButtonUp事件并不会被触发。 焦点切换:Tab 键切换焦点会干扰按钮的事件捕获 本文通过几个…...
备战!全国青少年信息素养大赛图形化编程-省赛——求最小公倍数
备战!全国青少年信息素养大赛图形化编程-省赛——求最小公倍数 题目可点下方去处,支持在线编程~ 求最小公倍数_scratch_少儿编程题库学习中心-嗨信奥 程序演示可点击下方去处,支持源码和素材获取~ 求最小公倍数-scratch作品-少儿编程题库学习…...
Vue3进行工程化项目,保姆级教学(编译软件:vscode)大部分编译平台适用
目录 1. 创建vue工程 1.1 第一步 1.2 选择名称和工件 1.3 选择语言 1.4 自动下载js 1.5 运行vue工程 1.6 成功页面 2. 更改vue工程安装的位置 3. 更改运行工程方式 第一步 第二步 编辑 第三步 调试 编辑 运行项目 前面所学都是vue3的基础,为了简…...
通过觅思文档项目实现Obsidian文章浏览器在线访问
觅思文档项目开源地址 觅思文档项目开源地址:https://gitee.com/zmister/MrDoc 觅思文档部署步骤概览 服务器拉取代码: git clone https://gitee.com/zmister/mrdoc-install.git && cd mrdoc-install && chmod x docker-install.sh &a…...
⭐️白嫖的阿里云认证⭐️ 第二弹【课时1:提示词(Prompt)技巧】for 「大模型Clouder认证:利用大模型提升内容生产能力」
「大模型Clouder认证:利用大模型提升内容生产能力」这个认证目前在阿里云认证中心还是免费的,简单几步就可以申请考试,有两次的免费考试机会。而且,这个课程中的内容对于所有普通用户来说都非常实用,课程整体长度也就3节课,非常快速就能学完。心动不如行动,赶紧开始吧!…...
零基础搭建!基于PP-ShiTuV2的轻量级图像识别系统(Docker+API部署指南)
以下是对该图像分类识别系统的的简单介绍: PP-ShiTuV2 是一个由百度飞桨团队发布的实用轻量级通用图像识别系统,由主体检测、特征提取、向量检索三个模块构成,适用于快速构建轻量级、高精度、可落地的图像识别应用image_classification是一个…...
阿克曼-幻宇机器人系列教程4- 建图
在之前的文章中,我们介绍了如何登录机器人,如何实现上位机与下位机之间的互通,还介绍了机器人的topic和message,以及如何通过命令行对topic、message进行对应的操作。 接下来,我们就要运用前面所学的所有知识进行综合…...
【方法论】如何构建金字塔框架
文章目录 一、自上而下法1、5步法2、案例说明:基于自上而下法构建金字塔结构来优化写作逻辑 二、自下而上法1、 自下而上法的“三步走”策略步骤1:列出所有思想要点步骤2:找出逻辑关系(因果或共性)步骤3:得…...
Ubuntu 18.04设置静态IP的方法(图形化操作)
0 前言 当路由器启用了DHCP功能,每次启动虚拟机下的Ubuntu(网络连接模式为桥接模式)分配到的IP可能是不一样的,不方便使用和调试(例如开发板加载镜像的主机IP地址也要跟着更改)。针对这些问题,…...
第12章 Java多线程机制
12.1 进程与线程 4种状态:新建、运行、中断和死亡。 (新建、运行、中断和死亡) 建立线程的两种方法:用Thread类或其子类。 线程新建后,必须调用 start () 方法使其进入就绪队列,才有机会获得 CPU 资源&a…...
AM32电调学习解读八:无感驱动相位波形解析
这是第八篇,本篇主要是解读换相波形,方便理解代码。 1、无感驱动波形图 1)ESC简图 2)比较器接线图 灵动微 BLDC 电机方波控制中的反电动势过零检测介绍 - 大大通(简体站) 3)未满duty波形 未满duty方便看出是高边驱…...
封装、继承、多态的理解
目录 1、封装 2、继承 3、多态 4、举例:计算机和外设 1、封装 封装是从使用者的角度,将某种复杂的事务,打包成一个整体,只对使用者提供方便使用的方式。 举例: 1> 胶囊:对于各种混合药物的封装 …...
使用vscode做python项目fastapi的开发
准备工作 安装必要软件 Python:确保安装 Python 3.8 或更高版本(FastAPI 推荐)。下载地址:https://www.python.org/downloads/ 验证安装: bash python --versionVS Code:下载并安装 VS Code:ht…...