目录
一,关联式容器
二,键值对
三,set
1)使用参考此文档
2)count 函数
3)multiset类
四,map
1. 模板参数介绍
2.operator[]介绍
3. multimap
英语比较好的同学可以自行查找文档 学习使用
set - C++ Reference (cplusplus.com)
在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面 存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别? 关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是
序列容器和关联容器的主要区别在于元素的排列方式和访问方式。序列容器按照元素的插入顺序进行排序,可以通过位置(索引)来访问元素;而关联容器按照键的顺序进行排序,可以通过键来访问元素。另外,序列容器支持快速的随机访问,而关联容器则不支持。
像这样:
template
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. set是按照一定次序存储元素的容器2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。5. set在底层是用二叉搜索树(红黑树)实现的。
1. 与map/multimap不同,map/multimap中存储的是真正的键值对,set中只放 value,但在底层实际存放的是由构成的键值对。 2. set中插入元素时,只需要插入value即可,不需要构造键值对。3. set中的元素不可以重复(因此可以使用set进行去重)。4. 使用set的迭代器遍历set中的元素,可以得到有序序列5. set中的元素默认按照小于来比较6. set中查找某个元素,时间复杂度为:$log_2 n$7. set中的元素不允许修改(为什么?)——保证树结构8. set中的底层使用二叉搜索树(红黑树)来实现。
set - C++ Reference (cplusplus.com)
使用比较简单,就只讲解一些特殊的点:
set结构特点:
1. 中序遍历树时呈现有序性。
2. 数据去重性。
set的count 函数,功能是统计相同key的个数。
功能意义不是很大,因为set类具有去重性,所以就跟find()函数功能重合。
multiset类与set一个重要区别——multiset类允许重复数据。
假设:2 2 3,插入2,2的位置可以是2的左右孩子; 当通过查找时(set一般通过中序查找方法)首先查到的2也就是中序最先遍历到的。
void Test_map()
{
map m1;
m1.insert(make_pair("string", "字符串")); // 可以写成pair("string", "字符串"),创建匿名对象
m1.insert(make_pair("func", "函数"));
m1.insert(make_pair("sort", "排序"));
m1.insert(make_pair("void", "空返回"));
auto dir = m1.begin();
while (dir != m1.end())
{
cout << (*dir).first << " second:" << (*dir).second << endl;
// cout<< dir->first ... ,dir是迭代器类型,STL一般是实现了->的重载
dir++;
}
cout << endl;
}
以上代码中使用了make_pair类,那这个make_pair类有什么特点??
本质上就是一个模板函数,里面封装了返回匿名对象,选择使用这么模板函数目的就是省略pair
可以简单理解为:通过该成员函数,返回键值表中的_val的引用。(不理解也没关系,后面逐步理解)
void Test_map_operator()
{
const char* arr[] = { "瓜", "花","瓜", "梨", "瓜" };
map count;
for (auto& e : arr)
{
auto ret = count.find(e);
if ( ret == count.end())
{
count.insert(make_pair(e, 1));
}
else
{
ret->second++;
}
// count[e]++;
}
for (auto& e : count)
{
cout << e.first << ":" << e.second << endl;
}
}
结果是正常的,然后我们将第一个auto的函数内容注释,替代为cout[e]++; 运行。运行结果跟我们的代码结果相同。这就有意思了。
文档中是这样解释这个代码的等效代码:
void Test_map_insert()
{
map m1;
m1.insert(make_pair("string", "字符串"));
m1.insert(make_pair("func", "函数"));
m1.insert(make_pair("sort", "排序"));
m1.insert(make_pair("void", "空返回"));
m1["afeng"]; // 查找,如果没有,则进行创建(修改)
m1["afeng"] = "阿峰"; // 修改
cout << m1["afeng"] << endl;
m1["afeng"] = "阿峰fc"; // 查找 + 修改
cout << m1["afeng"] << endl;
}
1. multimap中的key是可以重复的。2. multimap中的元素默认将key按照小于来比较3. multimap中没有重载operator[]操作(同学们可思考下为什么?)。(因为允许键值冗余,所以无法准确查找到对应的键值对)4. 使用时与map包含的头文件相同
下一期预告:我们从底层了解AVL树,上强度!
本小节就到这里了,感谢小伙伴的浏览,如果有什么建议,欢迎在评论区评论,如果给小伙伴带来一些收获请留下你的小赞,你的点赞和关注将会成为博主创作的动力。