在面向对象程序中,大多引入了容器的概念。那么什么是容器?实质上是一组相同类型对象的集合,但它不仅仅是数组那么简单,它实现了比数组更复杂的数据结构,能够实现更复杂的功能。C++标准模版库里提供了10种通用的容器,它基本可以解决程序中遇到的大部分问题。

什么是容器

C++中容器的定义如下:数据存储上,有一种对象类型,它可以持有其他对象或指向其他对象的指针,这种对象类型叫容器。通俗的说容器就是保存其他对象的对象,这种“对象”还包含了一些列处理其他对象的方法,这也体现了容器类的一个好处,“容器类对特定代码重用问题的良好的解决方案”。

容器另一个好处就是可以自行扩展,解决问题是我们不知道需要存储多少个对象,数组在这方面是个欠缺。容器可以为你申请内存、释放内存,并且使用最优的算法来执行你的命令。

通用容器的分类

(1)顺序性容器:各元素之间有顺序关系的线性表,是一种线性关系的有序集群,顺序容器中的元素均有固定的位置,除非用删除和插入来改变它的位置,这个位置和元素本身无关,和操作时间和地点有关。

vector:从后面快速删除和插入,访问任一元素;

deque:从前面或后面快速删除和插入,访问任一元素;

list:双联表,从任何位置插入和删除;

(2)关联式容器:非线性的树结构(二叉树结构),各元素之间没有严格的物理顺序。关联容器提供了根据元素特点排序的功能,迭代器根据元素特点“顺序”的取元素。

set:快速查找,不允许重复值;

multiset:快速查找,允许重复值;

map:一对多映射,基于关键字快速查找,不允许重复值;

multimap:一对多映射,基于关键字快速查找,允许重复值;

(3)容器适配器:让一种已存在的容器类型采用另一种不同抽象类型的工作方式来实现的一种机制。实质上仅发生了接口转换。

stack:后进先出;

queue:先进先出;

priority_queue:最高优先级第一个出列;

顺序性容器

(1)向量vector:我们可以把它看成动态数组,创建一个vector后,它会在内存中分配一块连续的区域存储数据,初试空间可以指定也可以有vector决定(capacity()函数返回值)。当数据存储空间超过分配空间,vector会重新分配一块内存区域,这样的分配很耗时,动作如下:

首先,vector申请一块更大内存区域;

然后,将原来的数据拷贝到新的内存区域;

其次,销毁原来内存块数据;

最后,释放原来内存空间。

所以,如果vector保存的数据量很大,这样的操作会导致很糟糕的性能。只有在预知空间大小的情况下,vector的性能才是最好的。

(2)双向链表List:双向线性链表结构,指针将所有元素链接起来。根据其结构特点,List检索性能不好,需要顺序查找,检索时间与目标元素位置成正比。但是它可以对快速的删除和插入。

(3)双端队列deque:对序列两端插入和删除的容器,可以快速的随即查找。它不像vector把所有元素存储在同一内存块,而是采用多个连续的存储块,并且一个映射结构中保存对这些块和元素顺序的跟踪。deque是vector和List优缺点的结合,它是处于两者之间的一种容器。支持[]及vector.at(),性能没有vector好。

关联容器

set,multiset,map,multimap都是非线性结构的树结构,采用高效的平衡检索二叉树——红黑树结构。

(1)set:一组元素的集合,元素值是唯一的,且按一定顺序排列,集合中每个元素称为集合的实例,内部采用链表结构组织;

(2)multiset:多重集合,实现方式类似set,元素值不唯一;

(3)map:提供“键--值”一一对应的数据存储能力,“键”在容器中不可重复,且按一定顺序排列;

(4)multimap:原理同上,“键”在容器中可重复。

关联容器插入和删除比vector快,比List要慢,每次插入删除后需要对元素重现排序;

关联容器检索比vector慢,但比List要快得多;

容器适配器

STL提供的三种适配器可以由某一种顺序容器去实现,默认stack和queue是基于deque容器实现,prioriety_queue是基于vector实现。

标签: none

评论已关闭