STL之序列式容器详解

所谓序列式容器,其中的元素都可序,但未必有序,C++语言本身提供了一个序列式容器array,STL另外再提供vector、list、deque、stack、queue、priority-queue等序列容器。其中stack和queue由于只是将deque改头换面而成,技术上被归类为一种配接器。下图为常用的序列式容器。

一、vector

    vector的数据安排以及操作方式,与array非常相似,两者的唯一差别在于空间的运用的灵活性。array是静态空间,一旦配置就不能改变,如果要换个大点的空间,需要程序员自己来(1、配置一块新空间,2、将元素从旧址一一搬往新址,3、把原来的空间还给系统);vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。

    vector维护的是一个连续线性空间,所以不论其元素型别为何,普通指针都可以作为vector的迭代器而满足所有必要条件,vector支持随机存取。为了降低空间配置时的速度成本,vector实际配置可能比客户端需求量更大一些,以备将来可能的扩充,下面为vector示意图。

    vector缺省使用alloc作为空间配置器,以元素大小为配置单位。当我们以push_back()将元素插入于vector尾部时,该函数首先检查是否还有备用空间,如果有就直接在备用空间上构造元素,并调整迭代器finish,使vector变大,如果没有备用空间,就扩充空间(重新配置、移动数据、释放空间《防止产生内存碎片》)。

二、list

相较于vector的连续线性空间,list就显得复杂许多,它的好处是每次插入或删除一个元素,就配置或释放一个元素空间因此,list对于空间不浪费,插入和删除的时间复杂度为o(1)。

    list迭代器正确的递增、递减、取值、成员取用操作是指,递增指向下一个节点,递减指向上一个节点,取值取的是节点的数据值,成员取用时取用的是节点的成员。STL list是一个双向链表迭代器具备前移、后移的能力。list有一个重要性质:插入和结合操作都不会有list迭代器失效,这在vector是不成立的,因为vector的插入操作可能造成原来的重新配置,导致原有的迭代器全部失效。list的元素删除操作也只有指向删除元素的那个迭代器失效,其他迭代器不受影响。

    SGI list不仅是一个双向链表,而且还是一个环状双向链表,所以它只需一个指针,便可完整表现整个链表,如图。

list缺省使用alloc作为空间配置器,以节点大小为配置单位。当我们以push_back()将元素插入list尾部时,此函数内部调用insert(),insert()是一个重载函数,有多种形式最简单的一种是:首先配置并构造一个节点,然后在尾端进行适当的指针操作,最后将节点插入进去,list不像vector那样有可能在空间不足时做重新配置、数据移动的操作,所以插入前的所有迭代器在插入操作之后都仍然有效。由于list是一个双向循环链表,只要我们把边界条件处理好,那么,在头部或者尾部插入元素的操作几乎是一样的,list内部提供一个所谓的迁移操作:将某连续范围的元素迁移到某个特定位置之前,节点间的指针移动而已。

三、deque

    vector是单向开口的连续线性空间,deque则是一种双向开口的连续线性空间,所谓双向开口,就是可以在头尾两端分别做元素的插入和删除操作,vector当然也可以头尾两端进行操作,但是其头部操作效率极差,无法接受。下图为deque示意图。

    deque和vector的最大差异,一在于deque允许常数时间内对头端进行元素的插入或移除操作,二在于deque没有所谓容量观念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。deque没有必要提供所谓的空间保留功能。vector只能向尾端“生长”,而deque可以在前端或者尾端增加新空间。

    deque采用一块所谓的map(不是STL的map容器)作为主控,这里的map是一小块连续空间,其中每个元素都是指针,指向另一段连续线性空间,称为缓冲区,缓冲区才是deque的存储空间主体,SGI STL允许我们指定缓冲区大小,默认值0表示使用512bytes缓冲区。 如图。

四、stack

    stack是一种先进先出的数据结构,它只有一个出口stack允许新增元素、移除元素、取得最顶端元素。但除了最顶端元素外,没有任何其他方式可以存取stack的其他元素,换言之,stack不允许有遍历行为。

五、queue

    queue是一种先进先出的数据结构,他有两个出口,queue允许新增元素、移除元素、从最底层加入元素等,queue不允许有遍历行为,deque是两头可进可出,queue是末端进,前端出。

在实际使用过程中,到底选择这几种容器中的哪一个,应该根据遵循以下原则:  

1、如果需要高效的随机存取,不在乎插入和删除的效率,使用vector;  

 2、如果需要大量的插入和删除元素,不关心随机存取的效率,使用list;  

 3、如果需要随机存取,并且关心两端数据的插入和删除效率,使用deque;  

 4、如果打算存储数据字典,并且要求方便地根据key找到value,一对一的情况使用map,一对多的情况使用multimap;  

 5、如果打算查找一个元素是否存在于某集合中,唯一存在的情况使用set,不唯一存在的情况使用multiset。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值