顺序容器
vector的特点
(1)指定一块如同数组一样的连续存储,但空间可以动态扩展。即它可以像数组一样操作,并且可以进行动态操作。通常体现在push_back()和pop_back()。
(2)随机访问方便,它像数组一样被访问。
(3)节省空间,因为它是连续存储,在存储数据的区域都是没有被浪费的,但是要明确一点:vector大多情况下并不是满存的,在未存储的区域实际是浪费的。
(4)在内部进行插入、删除操作效率非常低,这样的操作基本上是被禁止的。vector被设计成只能在后端进行追加和删除操作,其原因是vector内部的实现是按照顺序表的原理。
(5)只能在vector的最后进行push和pop,不能在vector的头进行push和pop。
(6)当动态添加的数据超过vector默认分配的大小时要进行内存的重新分配、拷贝与释放,这个操作非常消耗性能。所以要vector达到最优的性能,最好在创建vector时就指定其空间大小
list的特点
(1)不使用连续的内存空间,这样可以随意地进行动态操作。
(2)可以在内部任何位置快速地插入或删除,当然也可以在两端进行push和pop。
(3)不能进行内部的随机访问。
(4)相对于vector占用更多的内存。
deque的特点
(1)随机访问方便,即支持[ ]操作符,但性能没有vector好。
(2)可以在内部进行插入和删除操作,但性能不及list。
(3)可以在两端进行push和pop。
三者的比较
vector是一段连续的内存块,而deque是多个连续的内存块,list是所有数据元素分开保存,可以是任何两个元素没有连续。vector的查询性能最好,并且在末端增加数据的性能也很好,除非它重新申请内存段;适合高效地随机存储。list是一个链表,任何一个元素都可以是不连续的,但它都有两个指向上一元素和下一元素的指针。所以它对插入、删除元素性能是最好的,而查询性能非常差;适合大量地插入和删除操作而不关心随机存取的需求。deque是介于两者之间,它兼顾了数组和链表的优点,它是分块的链表和多个数组的联合。所以它有比list更好的查询性能,有比vector更好的插入和删除性能。如果用户需要随机存取又关心两端数据的插入和删除,那么deque是最佳之选。
关联容器
关联容器之间的差别
(1)set又称集合,实际上就是一组元素的集合,但其中所包含的元素的值是唯一的,且是按一定顺序排列的,集合中的每个元素被称作集合中的实例。因为其内部是通过链表的方式来组织,所以在插入的时候比vector快,但在查找和末尾添加数据时比vector慢。
(2)multiset是多重集合,其实现方式和set是相似的,只是它不要求集合中的元素是唯一的,也就是说集合中的同一个元素可以出现多次。
(3)map提供一种“键-值”关系的一对一的数据存储能力。其“键”在容器中不可重复,且按一定顺序排列。由于其是按链表的方式存储,它也继承了链表的优缺点。
(4)multimap和map的原理基本相似,它允许“键”在容器中可以不唯一。
关联容器的特点
(1)其内部实现是采用非线性的二叉树结构,具体地说是以红黑树的结构原理实现的。
(2)set和map保证了元素的唯一性,mulset和mulmap扩展了这一属性,可以允许元素不唯一。
(3)元素是有序的集合,默认在插入的时候按升序排列。
容器适配器
STL中包含三种适配器:栈stack、队列queue和优先级priority_queue。
适配器是容器的接口,它本身不能直接保存元素,它保存元素的机制是调用另一种顺序容器去实现,即:适配器保存一个容器,这个容器再保存所有元素.STL中提供的三种适配器可以由某一种顺序容器去实现。默认下stack和queue基于deque容器实现,priority_queue则基于vector容器实现。当然在创建一个适配器时也可以指定具体的实现容器,创建适配器时在第二个参数上指定具体的顺序容器可以覆盖适配器的默认实现。由于适配器的特点,一个适配器不是由任一个顺序容器都可以实现的。
栈stack
栈stack的特点是后进先出,所以它关联的基本容器可以是任意一种顺序容器,因为这些容器类型结构都可以提供栈的操作要求,它们都提供了push_back、pop_back和back操作。
队列queue
队列queue的特点是先进先出,适配器要求其关联的基础容器必须提供pop_front操作,因此其不能建立在vector容器上。
优先级队列priority_queue
优先级队列priority_queue适配器要求提供随机访问功能,因此不能建立在list容器上。