容器有顺序容器和关联容器。
前者包括vector,list,deque等;后者包括set,map,multiset,multimap等。
1.vector用数组实现,在内存中是一块连续的内存空间,所以支持随机访问。
支持尾端高效插入/删除操作,但其他位置的插入/删除操作效率低下,因为需要移动大量元素。
当添加的数据超过vector默认分配的大小时要扩容,分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素。
VS2015中以1.5倍扩容,GCC以2倍扩容。一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 。
2.list用双向链表实现。使用的是非连续性的内存空间存储,所以不支持随机访问,每个元素维护一个向前和一个向后的指针,所以支持向前和向后变量。支持高效的随机插入/删除操作。
3.deque用双端队列实现。结合了vector和list的功能。在两端插入和删除时间复杂度为O(1),在内部插入和删除时间复杂度为O(n).双端队列的数据被表示为一个分段数组,容器中的元素分段存放在一个个大小固定的数组中,此外容器还需要维护一个存放这些数组首地址的索引数组,由于分段数组的大小是固定的,并且它们的首地址被连续存放在索引数组中,因此可以对其进行随机访问,但效率比vector低很多。向两端加入新元素时,如果这一端的分段数组未满,则可以直接加入,如果这一端的分段数组已满,只需创建新的分段数组,并把该分段数组的地址加入到索引数组中即可。无论哪种情况都不需要对已有元素进行移动,因此在双端队列的两端加入新的元素都具有较高的效率。双端队列中间插入元素时,需要将插入点到某一端之间的所有元素向容器的这一端移动,因此向中间插入元素的效率较低,而且往往插入位置越靠近中间,效率越低。删除队列中元素时,情况也类似,由于被删除元素到某一端之间的所有元素都要向中间移动,删除的位置越靠近中间,效率越低。
a、若需要随机访问操作,则选择vector;
b、若已经知道需要存储元素的数目, 则选择vector;
c、若需要随机插入/删除(不仅仅在两端),则选择list
d、只有需要在首端进行插入/删除操作的时候,才选择deque,否则都选择vector。
e、若既需要随机插入/删除,又需要随机访问,则需要在vector与list间做个折中。
4.map
map容器中的元素是一些关键字-值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。key和value可以是任意你需要的类型。
红黑树:
容器中的关键字是有序非重复的,默认按关键字的升序排列。
插入数据有三种方式:
1.用insert函数插入pair数据 mp.insert(pair<int,string>(1,"stu1"));
2.用insert函数插入value_type数据 mp.insert(map<int,string>::value_type(1,"stu1"));
3.用数组方式插入 mp[1]="stu1";
前两种方式效果一样,当map中有这个关键字存在时,数据无法插入;用数组方式可以覆盖以前该关键字对应的值。
遍历也有三种方式:
1.正向迭代器
2.反向迭代器 reverse_iterator ,rbegin(), rend()
3.数组方式遍历。
查找map中的元素用find函数,找到返回数据所在位置的迭代器,没找到返回end()函数返回的迭代器
iterator->first 代表关键字,iterator->second代表存储的数据。
删除用erase,可以通过一个条目对象删除,可以删除一个范围,也可以通过关键字删除。
5.set
set只是单纯的关键字的集合.也是有序非重复,
6.multimap和mutiset允许关键字有重复。