键值密钥:解锁 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

微软BitNet开源:用Java在边缘设备部署7B级本地大模型(含ONNX Runtime优化)

微软BitNet开源:用Java在边缘设备部署7B级本地大模型(含ONNX Runtime优化)

文章目录 * 引言:当大模型开始"极简主义"生存 * 一、BitNet是啥?给大模型做"数字化减肥" * 1.1 1.58bit的魔法:三个数字走天下 * 1.2 为什么Java党这次能上桌吃饭 * 二、实战准备:把7B模型塞进边缘设备 * 2.1 硬件门槛:真不是越高越好 * 2.2 模型下载:别下错了版本 * 2.3 Java环境:ONNX Runtime是关键 * 三、核心代码:Java部署7B BitNet全实录 * 3.1 模型加载与初始化 * 3.2 推理Pipeline:分词、编码、解码

By Ne0inhk

VS Code中使用Git管理代码

以下内容由AI生成,亲测可用(除了最后的GitHub)。 可以把 Git 理解为一个 “超级后悔药” 或者 “时光机”。 为什么要用它? 你肯定有过这种经历:把代码文件名改成 code_v1.py, code_v2_final.py, code_v3_really_final.py… 最后自己都乱了。或者,你改了几行代码想优化算法,结果跑崩了,想改回去却忘了原来长什么样。 Git 就是为了解决这个问题。它能记录你每一次的修改,让你随时回退到过去的任何一个状态。 结合你的 WSL + VS Code 环境,我教你一套最直观、最少命令的“图形化”操作流程。 第一阶段:初次见面(配置身份) 在使用时光机之前,你得先告诉系统“是谁在使用它”,这样以后的记录才会显示是“你”

By Ne0inhk

计算机视觉新选择:阿里开源万物识别模型全面测评报告

计算机视觉新选择:阿里开源万物识别模型全面测评报告 核心结论先行:阿里最新开源的“万物识别-中文-通用领域”模型在中文语境下的图像理解能力表现出显著优势,尤其在细粒度物体识别、复杂场景解析和本地化部署效率方面超越主流英文预训练模型。本文基于真实环境部署与多维度测试,全面评估其性能表现、使用门槛与工程适用性。 一、背景与选型动因:为何需要中文优先的通用识别模型? 当前主流计算机视觉模型(如CLIP、YOLO系列、DINOv2等)大多以英文语料和西方场景数据为主进行训练,在面对中文环境下的实际业务需求时,常出现标签不匹配、语义理解偏差、文化特有物体识别失败等问题。例如,“糖葫芦”被识别为“水果串”,“共享单车”误判为“摩托车”。 在此背景下,阿里巴巴推出的万物识别-中文-通用领域模型应运而生。该模型专为中文用户设计,覆盖超过10万类中文标签,涵盖日常生活、工业制造、农业生态、城市治理等多个通用场景,支持零样本迁移(Zero-Shot Transfer),无需微调即可投入实际应用。 本次测评聚焦以下三个核心问题: - 模型在真实中文场景中的识别准确率如何? - 部署成本与推理效率

By Ne0inhk

Pencil Project完全指南:开源UI原型设计的效率革命

Pencil Project完全指南:开源UI原型设计的效率革命 【免费下载链接】pencilThe Pencil Project's unique mission is to build a free and opensource tool for making diagrams and GUI prototyping that everyone can use. 项目地址: https://gitcode.com/gh_mirrors/pe/pencil 在数字化产品设计领域,高效原型工具是连接创意与实现的关键桥梁。Pencil Project作为一款完全开源的原型设计工具,以其零成本门槛、跨平台兼容性和丰富的组件资源,正在重新定义UI/UX设计的工作流程。本文将从环境搭建到高级应用,全面解析这款工具如何帮助设计师从概念快速转化为可交互原型,释放创意潜能。 从零开始:Pencil

By Ne0inhk