键值密钥:解锁 C++ 关联容器的存储潜能

键值密钥:解锁 C++ 关联容器的存储潜能

目录

1:关联式容器

2:树形结构与哈希结构

3:键值对

4:Set And MultiSet

4.1:set的使用

4.1.1:set的模版参数列表

4.1.1.1:set的构造

4.1.1.2:set的迭代器

4.1.1.3:set的容量

4.1.1.4:set的修改

4.1.1.5:set的其他操作

4.2:multiset

4.3:Map And MultiMap

4.3.1:map的使用

4.3.1.1:map的迭代器

4.3.1.2:map的容量与元素访问

4.3.1.3:map中元素的修改

4.3.2:Map的总结

4.3.3:Multimap

4.3.3.1:Multimap的使用


1:关联式容器

  • vector、list、deque、forward_list等等,这些容器统称为序列是容器,因为底层是线性序列的数据结构,里面存储的是元素本身.
  • 关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key,value>结构的键值对,在数据检索比序列式容器效率更高,例如:set、map、unordered_set、unordered_map等.
  • 注意:C++STL当中的stack、queue和priority_queue属于容器适配器,它们默认使用的基础容器分别是deque、vector.

2:树形结构与哈希结构

根据应用场景的不同,C++的STL容器总共实现了两种不同结构的关联式容器:树型结构和哈希结构。

关联式容器       容器结构底层实现

set、map、multiset、multimap

树型结构平衡搜索树(红黑树)

unordered_set、unordered_map、unordered_multiset、unordered_multimap

哈希结构哈希表

其中,树型结构容器中的元素是一个有序的序列,而哈希结构容器中的元素是一个无序的序列.

3:键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息.

4:Set And MultiSet

4.1:set的使用

  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
    set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们.
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序.
  4. set容器通过key访问单个key元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代.
  5. set在底层是用二叉搜索树(红黑树)实现的.

4.1.1:set的模版参数列表

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

#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <set> #include <vector> void TestConsetuctor() { //构造空的set set<int> s1; vector<int> v1 = { 1,2,3,4,5,5,6,7,7 }; //迭代器区间构造 set<int> s2(v1.begin(), v1.end()); //拷贝构造 set<int> s3(s2); for(auto & element : s2) cout << element << " "; cout << endl; for (auto& element : s3) cout << element << " "; cout << endl; } int main() { TestConsetuctor(); }
4.1.1.2:set的迭代器

#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <set> #include <vector> void TestIterator() { vector<int> v1 = { 1,2,3,4,5,5,6,7,7 }; set<int> s1(v1.begin(), v1.end()); set<int>::iterator it = s1.begin(); while(it != s1.end()) { cout << *it << " "; it++; } cout << endl; //反向迭代器 set<int>::reverse_iterator rit = s1.rbegin(); while (rit != s1.rend()) { cout << *rit << " "; rit++; } cout << endl; } int main() { TestIterator(); }
4.1.1.3:set的容量
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <set> #include <vector> void Test_Capacity() { vector<int> v1 = { 1,8,9,7,5,6,4,3,2 }; set<int> s1(v1.begin(), v1.end()); cout << s1.size() << endl; cout << s1.empty() << endl; } int main() { Test_Capacity(); }
4.1.1.4:set的修改

#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <set> #include <vector> void Test_Modification() { set<int> s1; s1.insert(1); s1.insert(2); s1.insert(3); s1.insert(5); s1.insert(6); s1.insert(7); s1.insert(25); for (auto& element : s1) cout << element << " "; cout << endl; //测试find与erase函数 set<int>::iterator Position = s1.find(2); s1.erase(Position); Position = s1.find(3); size_t count = s1.erase(3); cout <<"删除的元素个数:>" << count << endl; for (auto& element : s1) cout << element << " "; cout << endl; cout <<"25的数量:>" << s1.count(25) << endl; } int main() { Test_Modification(); }
4.1.1.5:set的其他操作
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <set> #include <vector> void Test_Operation() { set<int> s1; s1.insert(1); s1.insert(2); s1.insert(3); s1.insert(5); s1.insert(6); s1.insert(7); s1.insert(25); set<int>::iterator it = s1.find(5); for (auto& element : s1) cout << element << " "; cout << endl; if (s1.end() != it) { cout << *it << endl; s1.erase(it); } else cout << "找不到" << endl; for(auto & element : s1) cout << element << " "; cout << endl; for (size_t i = 1; i < 10; i++) { s1.insert(i * 10); } for (auto element : s1) cout << element << " "; cout << endl; //获取的是闭区域 set<int>::iterator itlow = s1.lower_bound(25); //获取的是比70大的值,但是小于80 set<int>::iterator itup = s1.upper_bound(70); //[25,80) s1.erase(itlow, itup); for (auto& element : s1) cout << element << " "; cout << endl; } int main() { Test_Operation(); }

4.2:multiset

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的
  2. 在multiset中,元素的value也会识别它(因为multiset本身存储的是<value,value>组成的键值对,因此value本身就是key,key就是value,类型为T).multiset的元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或者删除.
  3. 在内部,multiset中的元素总是按照内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序.
  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列.
  5. multiset底层结构为红黑树.

PS:

  1. multiset中在底层中存储的是<value,value>的键值对.
  2. multiset的插入接口中只需要插入即可.
  3. 与set的区别是,multiset的元素可以重复,set中,value是唯一的.
  4. multiset中的元素不能被修改.
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <set> #include <vector> void Test_MultiSet() { //key模型搜索,排序 + 不去重 + 允许数据冗余 multiset<int> s1; s1.insert(1); s1.insert(1); s1.insert(3); s1.insert(2); s1.insert(5); s1.insert(7); s1.insert(9); s1.insert(15); s1.insert(35); for (auto& element : s1) cout << element << " "; } int main() { Test_MultiSet(); }

4.3:Map And MultiMap

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素.
  2. 在map中,键值key通常用于排序和唯一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:typedef pair<const key,T>value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的。
  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序
    对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树)).

4.3.1:map的使用

key:键值对中key的类型

T:键值对中value的类型

Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递).

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器.

注意:在使用map时,需要包含头文件.
4.3.1.1:map的迭代器

#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <map> #include <vector> void Test_MapIterator() { map<string, string>m1; pair<string, string>Kv1("Begin", "开始"); m1.insert(Kv1); m1.insert(pair<string, string>("End", "结束")); m1.insert(make_pair("Top", "顶部")); //多参数构造函数支持隐式类型转换 m1.insert({ "Bottom","底部" }); map<string, string>::iterator it = m1.begin(); while (it != m1.end()) { cout << (*it).first << ":" << it->second << endl; ++it; } } int main() { Test_MapIterator(); return 0; }
4.3.1.2:map的容量与元素访问

#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <map> #include <vector> void The_Pricinple() { map<string, string> dict; dict.insert({ "string","字符串" }); //插入(一般不这么用) dict["right"]; //插入 + 修改 dict["left"] = "左边"; //返回(返回的是Value的引用) cout << dict["string"] << endl; dict["right"] = "右边"; string str; while (cin >> str) { if (dict.count(str)) { cout << "在字典里面" << endl; } else { cout << "不在字典里面" << endl; } } } int main() { The_Pricinple(); return 0; }
注意:在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用,不同的是:当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常.
4.3.1.3:map中元素的修改
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <map> #include <vector> void Test_Modify() { map<string, string> Dictionary; Dictionary.insert({ "apple","苹果" }); Dictionary.insert(pair<string, string>("banana", "香蕉")); Dictionary.insert({"watermelon", "西瓜"}); Dictionary.insert({ "orange", "橙子" }); Dictionary.insert({ "lemon", "柠檬" }); for (auto& Kv : Dictionary) cout << Kv.first << ":>" << Kv.second << endl; cout << "----------------------------" << endl; Dictionary.erase("lemon"); Dictionary.erase("watermelon"); for (auto& Kv : Dictionary) cout << Kv.first << ":>" << Kv.second << endl; } int main() { Test_Modify(); return 0; }

4.3.2:Map的总结

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

4.3.3:Multimap

  1. Multimap是关联式容器,它按特定的顺序,存储由Key和value映射成的键值对<key,value>,其中多个键值对之间的key是可以重复的.
  2. 在multimap中,通过按照key排序和唯一地标识元素,而映射的value存储与key关联的内容,key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合key和value的键值对:typedef pair<const Key, T> value_type;
  3. 在内部,multimap的元素总是通过其内部比较对象,按照指定的特定严格弱排序对key进行排序

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

4.3.3.1:Multimap的使用

1.multimap中的key是可以重复的.
2. multimap中的元素默认将key按照小于来比较.
3. multimap中没有重载operator[]操作.
4. 使用时与map包含的头文件相同.

#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include <map> #include <vector> void Test_MultiMap() { string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" }; multimap<int, string> SortMap; map<string, int> CountMap; //插入 for (auto& element : arr) CountMap[element]++; //插入 for (auto& kv : CountMap) SortMap.insert({ kv.second,kv.first }); //默认按照key值排序 for (auto& kv : SortMap) cout << kv.first << ":" << kv.second << endl; cout << endl; } int main() { Test_MultiMap(); return 0; }

Read more

推出轮式人形机器人Zerith-H1(Home1)及垂直场景操作基础模型Zerith-V0 零次方机器人启动全模态数据采集中心,破解具身智能“卡脖子”难题

23,065 views 28 May 2025 产品定位:推出轮式人形机器人Zerith-H1(Home1)及垂直场景操作基础模型Zerith-V0,专注酒店、餐厅等类家庭服务场景,提供任务聚焦、交互轻量化的智能解决方案。 场景策略:采用“垂直场景切入-家庭场景延伸”路径,优先选择酒店清洁、餐厅备餐等流程明确的场景,降低技术复杂度,快速验证商业闭环。 技术验证:借鉴自动驾驶“锁定场景-泛化背景”模式,通过定义清晰任务边界(如布草整理)突破物体与背景泛化瓶颈,利用真实试错数据加速模型迭代。 模型创新:Zerith-V0采用“认知-行为”双系统架构,以

By Ne0inhk
【机器人】具身导航 VLN 最新论文汇总 | Vision-and-Language Navigation

【机器人】具身导航 VLN 最新论文汇总 | Vision-and-Language Navigation

本文汇总了具身导航的论文,供大家参考学习,涵盖2026、2025、2024、2023等 覆盖的会议和期刊:CVPR、IROS、ICRA、RSS、arXiv等等 论文和方法会持续更新的~ 一、🏠 中文标题版 2026 ✨ * [2026] SeqWalker:基于分层规划的时序视野视觉语言导航方法 [ 论文 ] [ GitHub ]   * [2026] UrbanNav:从网络规模人类轨迹中学习语言引导的城市导航方法 [ 论文 ] [ GitHub ]  * [2026] VLN-MME:面向语言引导视觉导航智能体的多模态大语言模型诊断基准 [ 论文 ] [ GitHub ]  * [2026] ASCENT: 实现楼层感知的零样本物体目标导航  [ 论文] [ GitHub ] 2025 😆 * [2025] ETP-R1:面向连续环境VLN的进化拓扑规划与强化微调方法 [ 论文 ] [ GitHub ] * [2025] NaviTrace:评估视觉语言模型在真实世界场景中的导航能力 [ 论文 ] [ GitHub ] * [2025]

By Ne0inhk

教你一步步在 服务器/本地(Linux/Windows) 部署鸣潮QQ机器人,并将其接入大语言模型,实现通过机器人进行库街区签到、练度查询、攻略查询等功能 (1)

准备工作 一台轻量级服务器/ 本地windows/linux能够在服务器/本地 科学上网 环境部署 笔者所演示的环境为阿里云服务器(2核CPU,2GIB内存,40GIB系统盘),操作系统为 Ubuntu 24.04. 确保已成功安装Python环境(版本须>3.8, 建议>=3.12,不建议>=3.13) 确保已成功安装git 如果你没有安装git且的系统是ubuntu,安装git只需要输入 如果系统为Windows,则自行前往 🔗官网 下载安装包安装即可 创建虚拟环境 从 Python 3.11 开始,Debian 和 Ubuntu 默认启用了 "Externally-Managed-Environment"(外部管理环境)保护机制,

By Ne0inhk
3、超越CRUD:用JeecgBoot低代码模式,一天搭建功能完备的请假审批系统

3、超越CRUD:用JeecgBoot低代码模式,一天搭建功能完备的请假审批系统

超越CRUD:用JeecgBoot低代码模式,一天搭建功能完备的请假审批系统 引言:低代码革命与JeecgBoot的崛起 在当今快速变化的商业环境中,企业应用开发的传统瓶颈日益凸显:开发周期长、成本高、对专业开发人员依赖度强、难以快速响应业务变化。根据Forrester Research的报告,超过60%的企业应用开发项目存在延期交付问题,而低代码开发平台正成为解决这一困境的关键技术。 JeecgBoot作为国内领先的Java低代码开发平台,凭借其强大的代码生成能力和可视化开发工具,让开发者能够以惊人的速度构建企业级应用。本文将通过一个完整的“请假审批系统”实战案例,深入解析JeecgBoot的低代码核心原理,并展示如何在一天内完成一个功能完备的后台系统开发。 一、JeecgBoot低代码架构深度解析 1.1 JeecgBoot整体架构概览 JeecgBoot采用经典的前后端分离架构,但其核心价值在于提供了一系列可视化低代码工具,大幅降低了开发门槛。下面的架构图展示了JeecgBoot的核心组件及其协作关系: 这种架构设计的核心优势在于分层解耦和工具集成。Jeecg

By Ne0inhk