中小企业网站构建设计,wordpress 大众点评,濮阳新闻联播,网络组建与维护试题目录
关联式容器
要点分析
键值对
pair介绍
set
模板参数列表#xff1a;
set的构造#xff1a; 常用接口
操作
multiset
map
map的构造
插入
make_pair
map的迭代器
operator[]
multimap
multimap中为什么没有重载operator[] 关联式容器
关联式容器也是用…目录
关联式容器
要点分析
键值对
pair介绍
set
模板参数列表
set的构造 常用接口
操作
multiset
map
map的构造
插入
make_pair
map的迭代器
operator[]
multimap
multimap中为什么没有重载operator[] 关联式容器
关联式容器也是用来存储数据的和vector、list这样的序列式容器不同的是它里面存储的是key,value结构的键值对在数据检索时效率很高。在STL库中有两种不同结构的关联式容器树形结构与哈希结构。树形结构的关联式容器包括set、multiset、map、multimap这四种也是下面要谈论的主要内容。
要点分析
键值对
要走进关联式容器首先要理解键值对的概念这一概念在之前的文章中也有介绍键值对是用来表示对应关系的结构结构中一般包含两个成员变量key和value,key代表键值value代表与之对应的信息。例如下述图片中的名著和作者就是一一对应的关系 pair介绍
pair这个类是对键值对的定义将一对不同类型的数据组合T1和T2组合在一起结构中包含两个成员变量分别是key和value,它们的类型是T1和T2。 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){}
}
set
set的底层是用二叉搜索树来实现的。set中只放value但在底层实际存放的是由value, value构成的键值对。
模板参数列表 ●T: set中存放元素的类型实际在底层存储value, value的键值对。 ●Compareset中元素默认按照小于来比较。 ●Allocset中元素空间的管理方式使用STL提供的空间配置器管理。
set的构造 void TestSet3()
{//构造空的setsetint s1;//根据区间构造setint arr[10] {0,1,3,4,5,7,9,6,2,8};int size sizeof(arr) / sizeof(int);setint s2(arr,arrsize);} 常用接口
修改操作 插入
void SetInsert()
{setint ss;ss.insert(5);ss.insert(3);ss.insert(2);ss.insert(2);ss.insert(4);ss.insert(2);ss.insert(2);for (auto e : ss){cout e ;}
} 需要注意的是当要插入的数据已经存在将不会继续插入。
删除
void Seterase()
{setint ss;ss.insert(1);ss.insert(2);ss.insert(3);ss.insert(4);ss.insert(5);for (auto e : ss){cout e ;}cout endl;ss.erase(3);for (auto e : ss){cout e ;}cout endl;ss.erase(5);for (auto e : ss){cout e ;}cout endl;ss.erase(1);for (auto e : ss){cout e ;}
} 交换
void setswap()
{setint s1;s1.insert(1);s1.insert(3);s1.insert(5);s1.insert(7);s1.insert(9);cout 交换前s1;for (auto e : s1){cout e ;}setint s2;s2.insert(2);s2.insert(4);s2.insert(6);s2.insert(8);s2.insert(10);cout endl;cout 交换前s2;for (auto e : s2){cout e ;}s1.swap(s2);cout endl;cout 交换后s1;for (auto e : s1){cout e ;}cout endl;cout 交换后s2;for (auto e : s2){cout e ;}
} 清理
void setclear()
{setint s1;s1.insert(2);s1.insert(4);s1.insert(6);s1.clear();
} 迭代器 void set_iterator()
{int arr[10] {1,3,5,7,9,2,4,6,8,10};int size sizeof(arr) / sizeof(int);setint s1(arr,arrsize);//auto it1 s1.begin();setint::iterator it1 s1.begin();while (it1 ! s1.end()){cout *it1 ;it1;}//auto it2 s2.rbegin()setint::reverse_iterator it2 s1.rbegin();cout endl;while (it2 ! s1.rend()){cout *it2 ;it2;}
} 容量 void setempty_size()
{int arr[10] { 1,3,5,7,9,2,4,6,8,10 };int size sizeof(arr) / sizeof(int);setint s1(arr, arr size);cout 是否为空 s1.empty() endl;cout 有效元素个数 s1.size() endl;s1.clear();cout 是否为空 s1.empty() endl;cout 有效元素个数 s1.size() endl;
} 操作 find:
void setfind()
{int arr[10] { 1,3,5,7,9,2,4,6,8,10 };int size sizeof(arr) / sizeof(int);setint s1(arr, arr size);for (auto e : s1){cout e ;}cout endl;auto it s1.find(5);if (it ! s1.end()){cout 找到了 *it endl;}else{cout 没找到 endl;}it s1.find(100);if (it ! s1.end()){cout 找到了 *it endl;}else{cout 没找到 endl;}
} count:
void setcount()
{int arr[10] { 1,3,1,7,1,2,1,6,8,10 };int size sizeof(arr) / sizeof(int);setint s1(arr, arr size);for (auto e : s1){cout e ;}cout endl;cout s1.count(1) endl;cout s1.count(2) endl;cout s1.count(50) endl;
} 对于count这个接口你可能不太理解它为什么会存在它好像只能确定数据是否出现过查找数据已经有find了好像没什么“用武之地”。哈哈哈它的“志向”当然不在此处我们接着向下看
multiset
multiset在接口的用法上大致相同相比较set而言multiset允许重复数据的出现
void _multiset()
{int arr[10] { 1,3,1,7,1,2,1,6,8,10 };int size sizeof(arr) / sizeof(int);multisetint s(arr,arrsize);for (auto e : s){cout e ;}} count接口上场
void _multiset_count()
{int arr[10] { 1,3,1,7,1,2,1,6,2,10 };int size sizeof(arr) / sizeof(int);multisetint s(arr, arr size);for (auto e : s){cout e ;}cout endl;cout s.count(1) endl;cout s.count(2) endl;cout s.count(10) endl;
} 小问题既然multiset允许数据的重复那么当我们查找数据的时候找到的是哪一个呢
void _multiset_find()
{int arr[10] { 1,3,1,7,1,2,3,6,3,10 };int size sizeof(arr) / sizeof(int);multisetint s(arr, arr size);for (auto e : s){cout e ;}cout endl;multisetint::iterator it s.find(3);while (it ! s.end()){cout *it ;it;}
} 测试后发现find找到的位置是中序遍历第一次找到的元素位置。其余接口和set的使用大多一样这里就不在测试了。
map ●key: 键值对中key的类型 ●T 键值对中value的类型
map的构造 插入 查询文档了解到insert的返回值是一个pair,需要的参数也是一个pair。
void maptest2()
{mapstring, string notepad;notepad.insert(pairstring,string(张三,赤峰));notepad.insert(pairstring,string(李四,北京));for (auto e : notepad){cout e.first : e.second endl;}//auto pr notepad.insert(pairstring, string(王麻子, 西安));pairmapstring,string::iterator,bool pr notepad.insert(pairstring, string(王麻子, 西安));cout (pr.first)-first :(pr.first)-second endl;
} 接收insert后的返回值并进行分析 通过上述测试对insert有了大致的了解但是插入的过程中代码显得好笨重pairstring,string......每次都要写好长好长这个时候就要介绍一个帮我们偷懒的朋友了make_pair!
make_pair make_pair的返回值是一个pair,根据模板参数T1,T2确定pair中两个元素的类型根据参数x,y确定元素值。也就是说在上述代码插入数据的部分可以这样写
mapstring, string s;
s.insert(make_pair(张小红,内蒙古)); map的迭代器
void mapTest4()
{mapstring, string notepad;notepad.insert(make_pair(张三, 赤峰));notepad.insert(make_pair(李四, 北京));notepad.insert(make_pair(王麻子, 西安));notepad.insert(make_pair(张小红, 内蒙古));mapstring, string::iterator it1 notepad.begin();cout -----------正向迭代器----------- endl;while (it1 ! notepad.end()){//cout (*it1).first : (*it1).second endl;cout it1-first : it1-second endl;it1;}cout -----------反向迭代器----------- endl;mapstring, string::reverse_iterator it2 notepad.rbegin();while (it2 ! notepad.rend()){//cout (*it2).first : (*it2).second endl;cout it2-first : it2-second endl;it2;}
} operator[] operator[]重载和以往的[]重载相比有一些不一样传过来的参数是key,返回值是value。在这过程中首先向this插入make_pairinsert的返回值类型又是一个pairiterator,bool,访问pair的first元素获取到一个迭代器迭代器找到的位置又是一个pairkeyvalue,返回该pair的第二个元素也就是value。 观察上图分析后[]除了访问元素外还能进行查找修改插入的操作。
void mapTest5()
{mapstring,int grade;//插入前提是该数据原来并不存在grade[语文];//[]返回值是value,可以对其进行修改grade[语文] 99;//查找根据key查找对应的valuecout grade[语文] endl;
} 应用场景1统计“象牙山村”选举票数
void mapset1()
{mapstring, int count;string arr[10] {刘能,谢广坤,谢广坤,赵四,王老七,刘能,刘能,王老七,刘能,谢广坤};for (auto e : arr){auto it count.find(e);if (it count.end()){//插入count.insert(make_pair(e,1));}else{//(*it).second;it-second;}}cout -------象牙山选举大会-------- endl;for (auto e : count){cout e.first : e.second 票 endl;}
}使用[]的版本
void maptest1()
{mapstring, int count;string arr[10] {刘能,谢广坤,谢广坤,赵四,王老七,刘能,刘能,王老七,刘能,谢广坤};for (auto e : arr){count[e];}cout -------象牙山选举大会-------- endl;for (auto e : count){cout e.first : e.second 票 endl;}
} 对比两组代码后者是不是简单了不少呢[]使用起来非常的方便但同时也是一把双刃剑需要我们对其底层原理有所了解在使用的时候也一定要细心。
multimap
multimap和map的区别map中的key是唯一的而multimap中key是可以重复的。
void Test6()
{multimapstring, string dict;dict.insert(make_pair(左边, left));dict.insert(make_pair(左边, LEFT));dict.insert(make_pair(左边, ****));
} multimap中为什么没有重载operator[]
在了解过map的[]重载后你知道[]需要key来访问value。那么在multimap这种允许key重复出现的场景下xxx[key]访问到的value不一定是唯一的这时的修改操作也不知道该去修改哪一个value所以multimap没有重载[]。 小结关联式容器的介绍到这就结束了有些接口没有涉及到有兴趣的小伙伴可以继续查找文档探索 set - C Reference map - C Reference