维基百科定义:
In computer science, a container is a class, a data structure,[1][2] or an abstractdata type (ADT) whose instances are collections of other objects. In other words;they are used for storing objects in an organized way following specific accessrules.
图示:
顺序性容器:
向量 vector
是一个线性顺序结构。相当于数组,但其大小可以不预先指定,并且自动扩展。它可以像数组一样被操作,由于它的特性我们完全可以将vector 看作动态数组。
双向链表list
是一个线性链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。
双端队列deque
是一种优化了的、对序列两端元素进行添加和删除操作的基本序列容器。它允许较为快速地随机访问,但它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结构中保存对这些块及其顺序的跟踪。向deque 两端添加或删除元素的开销很小。它不需要重新分配空间,所以向末端增加元素比vector 更有效。
实际上,deque 是对vector 和list 优缺点的结合,它是处于两者之间的一种容器。
vector 、list 、deque 在内存结构上的特点:
vector 是一段连续的内存块,而deque 是多个连续的内存块, list 是所有数据元素分开保存,可以是任何两个元素没有连续。
vector 的查询性能最好,并且在末端增加数据也很好,除非它重新申请内存段;适合高效地随机存储。
list 是一个链表,任何一个元素都可以是不连续的,但它都有两个指向上一元素和下一元素的指针。所以它对插入、删除元素性能是最好的,而查询性能非常差;适合大量地插入和删除操作而不关心随机存取的需求。
deque 是介于两者之间,它兼顾了数组和链表的优点,它是分块的链表和多个数组的联合。所以它有被list 好的查询性能,有被vector 好的插入、删除性能。如果你需要随即存取又关心两端数据的插入和删除,那么deque 是最佳之选。
关联容器:
set, multiset, map, multimap 是一种非线性的树结构,具体的说采用的是一种比较高效的特殊的平衡检索二叉树—— 红黑树结构。(至于什么是红黑树,我也不太理解,只能理解到它是一种二叉树结构)
因为关联容器的这四种容器类都使用同一原理,所以他们核心的算法是一致的,但是它们在应用上又有一些差别,先描述一下它们之间的差别。
set:又称集合,实际上就是一组元素的集合,但其中所包含的元素的值是唯一的,且是按一定顺序排列的,集合中的每个元素被称作集合中的实例。因为其内部是通过链表的方式来组织,所以在插入的时候比vector 快,但在查找和末尾添加上被vector 慢。
multiset:是多重集合,其实现方式和set 是相似的,只是它不要求集合中的元素是唯一的,也就是说集合中的同一个元素可以出现多次。
map :提供一种“键- 值”关系的一对一的数据存储能力。其“键”在容器中不可重复,且按一定顺序排列(其实我们可以将set 也看成是一种键- 值关系的存储,只是它只有键没有值。它是map 的一种特殊形式)。由于其是按链表的方式存储,它也继承了链表的优缺点。
multimap :和map 的原理基本相似,它允许“键”在容器中可以不唯一。
顺序容器示例:
//顺序容器list #include<iostream> #include<list> using namespace std; int main() { list<int> list_object; for(int i = 0;i <=5;i++) list_object.push_back(i); cout<<"List containers:\n"; list<int>::iterator iter; for(iter = list_object.begin();iter != list_object.end();iter++) cout<<*iter<<" "; cout<<endl; cout<<"Setting all entries to 0:\n"; for(iter = list_object.begin();iter != list_object.end();iter++) *iter = 0; cout<<"List now containers:\n"; for(iter = list_object.begin();iter != list_object.end();iter++) cout<<*iter<<" "; cout<<endl; return 0; }
结果:
List containers: 0 1 2 3 4 5 Setting all entries to 0: List now containers: 0 0 0 0 0 0