序列式容器:
vector:
变长容器,可以根据数据的插入删除来重新构建容器容量。它是由三个迭代器来表示(起始字节位置,最后一个元素位置,占用的所有内存末尾位置),底层存储接口还是数组。
array:
(c++11新加的):和普通数组一样,都属于定长容器。只是封装了许多常用的接口,方便使用。
注:vector和array提供了size和判空获取机制;
vector和array提供了两个容器对象内容交换方法;
迭代器失效问题。
list:
有双向链表实现(有的是双向循环列表),内存数据是不连续的,所以需要指针来维系,节点结构上除了值还有两个指针。通过重载的*, ++等实现取值遍历一系列操作。
deque:(双端队列)
内存结构:一个指针数组,通过数组中的指针关联多个互相不连续的连续存储块。添加或删除元素开销较小,他不会有大量的数据拷贝,也能较快的访问。结合了list和vector的优点。
forward_list(单向链表)
关联式容器:
map:
基于RBTree实现(为什么要基于红黑树[map场景,红黑树优势])
map场景本质是动态查找过程,动态包含了插入删除,且数据量通常较大且元素类型随意,基于内存实现,因此需要考虑效率和成本。
注:不一定要基于红黑树,跳表/B-Tree都可以。
multi_map键值不唯一,unordered_map底层是哈希(散列)函数实现。无序的。
优秀文章链接
set:(集合)
底层实现还是RBTree,set键值唯一。和map不同的是它的键值就是值,值就是键值。
适配器:
stack:
基于deque实现,后进先出,没有遍历行为,因此没有迭代器。
queue:
基于deque实现,FIFO,没有遍历行为,因此没有迭代器。
priority_queue:(优先队列)
可以自定义实现它的底层容器(须底层是数组)和比较函数,(大顶堆和小顶堆)
比较:
内存空间 | 查询 | 插入删除 | |
---|---|---|---|
array | 静态连续空间 | O(1) | 不允许 |
vector | 动态连续空间 | O(1) | 自动扩展size,但需要copy元素,O(n)(从末尾插入/删除则O(1)) |
list | 动态非连续空间 | O(n) | O(1) |
deque | 动态(分段)连续空间 | O(1) | 扩展size不需要copy元素,从头、尾两端插入/删除O(1) |
stack | 动态空间 | top() | FILO O(1) |
queue | 动态空间 | top() | FIFO O(1) |
priority_queue | 动态空间 | top() | O(1) |
map | 动态空间 | O(logN) | 插入 O(logN) |
set | 动态空间 | O(logN) | 插入 O(logN) |