文章目录
写在前面
容器的分类:
- 序列式(元素可排序):array,vector,heap,priority-queue,list,deque,stack,queue
- 关系型:RB-tree(非公开),set, map, multiset,multimap,hashtable,hash_set,hash_map,hash_multiset,hash_multimap
1.1 vector
vevtor是动态空间, 随着元素的增加,其内部机制会自行扩充空间以容纳新的元素。扩充空间会涉及到数据的移动、释放旧空间、配置新空间的操作。
1.1.1容量扩增(面试问过)
增加新元素时,如果超过当时的容量,则容量会扩增为原来的两倍,如果容量仍不足,就扩张至足够大的容量(原容量+所需容量)。
特别注意:容量的动态扩增并不是在原有的空间之后接续新的空间,因为无法保证原空间之后还有可配置的空间,而是以原空间的两倍配置新的空间,然后将原空间的内容拷贝过来,开始在原内容之后增加新的元素,所以对于vector的任何操作,一旦引起了空间重新配置,指向原vector的所有迭代器都失效了。
push_back操作
insert操作
- 当vector不用扩增时,需要判断插入位置之后的元素个数bn与插入的元素的个数n的大小关系
当插入位置之后的元素个数bn大于插入元素的个数n时(bn > n)
- 首先将插入位置之后的最后n个元素移动到序列(增加n个元素之后的序列)的尾部
- 再将剩余的元素移动到刚刚移动的那n个元素的前面
- 最后将待插入的元素插入到序列中
当插入位置之后的元素个数bn小于插入元素的个数n时(bn <= n)
- 首先将(n - bn)个新增元素插入到原序列的尾部
- 再将原序列中需要移动的元素移动到新序列的尾部
- 最后将待插入的bn个新的元素插入到序列中所指示的位置
- 当插入n个元素需要扩充空间时
- 申请新的空间
- 将原序列中的插入位置之前的元素拷贝到新的空间中
- 在上述位置之后插入n个元素
- 在新插入的n个元素之后插入原序列插入位置之后的元素
代码:
1.2 list
list是一个双向链表,每一个节点都包含一个信息块、前驱指针、后继指针。
重要性质:对list进行插入和删除节点不会造成list原迭代器失效
1.3 deque
相比vector是单向开口的连续空间,deque是双向开口的连续空间。
- 在进行空间的动态增长时,vector采用申请新的空间、移动元素、删除旧空间的方式。deque要复杂的多,它只是在头插和头删元素时比vector高效。
- deque相比list, deque支持元素的随机访问
- deque在插入删除元素时,再首尾插入元素不会使任何迭代器失效,在首尾删除元素会使指向该元素的迭代器失效,在中间插入删除元素时会使所有的迭代器失效
deque的底层实现机制
deque采用一段一段的定量连续空间组成,每一块的大小默认为512字节,每一块所能存储的元素的个数由所存储的数据类型决定,块由map来管理
1.4 stack
stack(末端进,末端出)是以deque作为底层的实现机制,stack被称为容器适配器。
1.5 queue
queue(末端进,前端出)以deque作为底层的实现机制
1.6 heap
1.7 priority_queue
priority_queue是一个拥有权值观念的queue,它只能在末端进,前端出,但是元素并不是按照进入的顺序排列,而是按照元素的权值进行排列,权值高的在最前面。
priority_queue底层是max_heap,max_heap底层是一个用vector实现的完全二叉树
2 关联式容器
每一组元素都是有一个键(key)和一个值(value)。
- 关联式容器没有所谓的头尾。
- 关联式容器底层是红黑树实现的
2.1 set
- set不允许有两个相同的键值
- set不允许通过迭代器改变其键值
- 对set进行新增元素删除元素时,其之前的迭代器依然有效,被删除的元素例外
- 在set中查找元素时,采用set中的find方法比STL中的find算法更高效,因为STL中的find算法只是循环搜寻,而set中的find算法是在红黑树上进行搜寻
2.2 map
- map中的所有元素都是根据**键值(Key)**进行自动排序
- 不可以通过迭代器改变map的键值(Key),但可以改变实值(value)
- 对map进行新增操作和删除操作时,之前的迭代器依然有效,但被删除的元素的迭代器例外
2.3 multiset
- 允许键值重复
2.4 multimap
- 允许键值重复