1.vector

Vector是顺序容器,是一个动态数组,支持随机存取、插入、删除、查找等操作,在内存中是一块连续的空间。

注意:vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。

注意:

根据vector的插入和删除特性,以及扩容规则,我们在使用vector的时候要注意,在插入位置和删除位置之后的所有迭代器和指针引用都会失效,同理,扩容之后的所有迭代器指针和引用也都会失效。

Vector初始时,容量为0.插入1个元素,扩展为1. 然后每次都是扩展成2倍。


2.map

C++中map主要分为两种:map与unordered_map

他们的区别在于:

对于map,其底层是基于红黑树实现的,优点如下:

1)有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作

2)map的查找、删除、增加等一系列操作时间复杂度稳定,都为logn

缺点如下:

1)查找、删除、增加等操作平均时间复杂度较慢,与n相关

对于unordered_map来说,其底层是一个哈希表,优点如下:

查找、删除、添加的速度快,时间复杂度为常数级O©

缺点如下:

因为unordered_map内部基于哈希表,以(key,value)对的形式存储,因此空间占用率高

Unordered_map的查找、删除、添加的时间复杂度不稳定,平均为O©,取决于哈希函数。极端情况下可能为O(n)


3.map和set区别

(1)map中的元素是key-value(关键字—值)对:关键字起到索引的作用,值则表示与索引相关联的数据;Set与之相对就是关键字的简单集合,set中每个元素只包含一个关键字。

(2)set的迭代器是const的,不允许修改元素的值;

map允许修改value,但不允许修改key (key是const)。其原因是因为map和set是根据关键字排序来保证其有序性的,如果允许修改key的话,那么首先需要删除该键,然后调节平衡,再插入修改后的键值,调节平衡,如此一来,严重破坏了map和set的结构,导致iterator失效,不知道应该指向改变前的位置,还是指向改变后的位置。所以STL中将set的迭代器设置成const,不允许修改迭代器的值;而map的迭代器则不允许修改key值,允许修改value值。

(3)map支持下标操作,set不支持下标操作。map可以用key做下标,map的下标运算符[ ]将关键码作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码和mapped_type类型默认值的元素至map中,因此下标运算符[ ]在map应用中需要慎用,const_map不能用,只希望确定某一个关键值是否存在而不希望插入元素时也不应该使用,mapped_type类型没有默认值也不应该使用。如果find能解决需要,尽可能用find。


4. list

image-20191207210437516

list底层实现其实就是 双向环形链表。


5.dequeue

image-20191207210647570

一开始我可以双向队列和vector实现一样,只不过双向队列能往两边扩充。实际上双向队列是 map+array的形式。


6.其他容器的实现

image-20191207210900980

c++有一个容器适配器的概念,可以自己实现容器。


7.线程安全

c++容器的实现都没有考虑线程安全的问题。所有使用的时候要注意不要同时多个线程写同一个容器。