本文主要是介绍【STL源码剖析】总结笔记(2):容器(containers)概览,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
00 写在前面
容器(containers)是STL的重要组成部分之一,也是非常值得我们深入研究的部分。各种vector、map、set的使用极大地提高了我们解决问题的效率。
每个容器内部都有着其独特的实现方式以及一些需要我们了解的要点,这些会是文章中的侧重点。
01 容器的结构与分类
概述
容器大致分为序列式容器(Sequence),关联式容器(Associative)和无序容器(Unordered),无序容器也可以归为关联式容器内。
分类
序列式容器(Sequence)
- array:数组,是一种固定大小的结构,静态空间,配置后大小就不能改变。
- vector:动态数组,单向开口的线性连续空间,可动态配置空间,原理是每次扩容时二倍增长,再将原空间数据拷贝到新空间中。
- deque:是一种双向开口的线性连续空间,可在头和尾进行插入和删除操作。
- list:链表结构,不是线性连续空间,使用指针寻址,这里指的是双向链表。
- forward-list:单向链表
- stack/queue:栈和队列,底层都是使用双向开口的deque包装后实现的。
关联式容器(Associative)
- set/multiset:以红黑树为基础的结构,可以存放key。对于set来说key不可以重复,multiset的key可以重复。
- map/multimap:以红黑树为基础的结构,可以存放key和value,对于map来说key不可以重复,multimap的key可以重复。
- unordered set/multiset:以哈希表为基础的结构,可以存放key。对于set来说key不可以重复,multiset的key可以重复。
- unordered map/multimap:以哈希表为基础的结构,可以存放key和value,对于map来说key不可以重复,multimap的key可以重复。
对比关系:
集合 | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
---|---|---|---|---|---|---|
std::set | 红黑树 | 有序 | 否 | 否 | O(logn) | O(logn) |
std::multiset | 红黑树 | 有序 | 是 | 否 | O(logn) | O(logn) |
std::unordered_set | 哈希表 | 无序 | 否 | 否 | O(1) | O(1) |
映射 | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
---|---|---|---|---|---|---|
std::map | 红黑树 | key有序 | key不可重复 | key不可修改 | O(logn) | O(logn) |
std::multimap | 红黑树 | key有序 | key可重复 | key不可修改 | O(logn) | O(logn) |
std::unordered_map | 哈希表 | key无序 | key不可重复 | key不可修改 | O(1) | O(1) |
02 容器间的关系
先来看一张关系图:
这里的缩进显示代表着基层与衍生层的关系,而衍生不是继承,而是复合。
比如heap和priority里面有vector作为基层。set、map有红黑树作为基层。
也有一些非标准的容器在里面,比如slist,hash开头的等等。在C++ 11中slist改名为forward-list,hash开头的全部改为unordered开头。
注:这里的sizeof()埋一个小伏笔,后面会有具体大小的对比。另外GNU4.9有很多设计变得复杂了,比如使用了很多继承,但实际功能区别不大。
03 总结
在了解了容器的大致内容之后,我们可以从最熟悉的vector入手来看看内部的实现细节。
而在其他容器中也会有很多值得学习的地方,比如list中会体现出迭代器(iterators)设计的精妙之处,在set和map中会体现红黑树的实现等等,后续单独总结。
这篇关于【STL源码剖析】总结笔记(2):容器(containers)概览的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!