STL 容器类小结

顺序容器


顺序容器包括:vector、deque、list、forward_list、array以及string

vector


可变大小数组,即将元素保存在一段连续的内存空间中。支持快速随机访问。在尾部之外的位置插入删除元素可能会很慢。
PS:当元素已经占满了预先分配的内存空间,插入新的元素时,开辟一段新的内存空间,大小为之前vector的两倍,再将vector内的元素拷贝到新的内存空间内。

list


双向链表。只支持双向顺序访问。在list任何位置进行插入、删除都很快。

deque


双向队列,双端开口的连续空间(逻辑上看来是这样的,但并不是vector那样的线性连续空间)。在头尾位置插入删除数据很快。

deque与vector的差异:

  • deque允许常数时间内对头端进行数据的插入或删除。
  • deque没有所谓的容量观念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。

deque的实现原理:
deque实际上由一段一段的定量连续空间链接构成,一旦有必要在deque的头部或尾部增加新的空间,便配置一段定量连续空间,串接在整个deque的头端或尾端。
因此deque必须要有一个中央控制组件来维护整体连续的假象并提供随机存取的接口。
deque采用一小块连续空间称为所谓的“map”,“map”内的每一个元素都是指针,指向另一段较大的连续内存空间,被称为缓冲区,缓冲区既是deque存储空间的主体。
如何维持“整体连续“的假象?
通过对deque的迭代器的operator++与operator–的重载来实现。
通过源码可以看到deque的迭代器类内有这么几个成员
T* cur;  此迭代器所指缓冲区中的现行元素
T* first; 此迭代器所指缓冲区中的头
T* last; 此迭代器所指缓冲区中的尾
map_point node; 指向“map”中对应的元素

stack 和 queue


stack是以deque或list为底部结构,并将其接口改变,以符合“先进后出”的特性来实现的。严格来说不算STL容器中的一类,STL把这种称为container adapter。
PS:stack没有迭代器
queue
queue与stack同理。

其他顺序容器


forward_list 单向链表
string 与vector相似的容器,专门用于保存字符。

关联容器


set, multiset, map, multimap 是一种非线性的树结构,具体的说采用的是一种比较高效的特殊的平衡检索二叉树—— 红黑树结构。
因为关联容器的这四种容器类都使用同一原理,所以他们核心的算法是一致的,但是它们在应用上又有一些差别,先描述一下它们之间的差别。

set


又称集合,实际上就是一组元素的集合,但其中所包含的元素的值是唯一的,自动被排序,集合中的每个元素被称作集合中的实例,元素值不能改变。因为其内部是通过链表的方式来组织,所以在插入的时候比vector 快,但在查找和末尾添加上比vector 慢。

multiset


是多重集合,其实现方式和set 是相似的,只是它不要求集合中的元素是唯一的,也就是说集合中的同一个元素可以出现多次。

map


提供一种“键- 值”关系的一对一的数据存储能力。其“键”在容器中不可重复,且按一定顺序排列(其实我们可以将set 也看成是一种键- 值关系的存储,只是它只有键没有值。它是map 的一种特殊形式)。

multimap


和map 的原理基本相似,它允许“键”在容器中可以不唯一。
关联容器的特点是明显的,相对于顺序容器,有以下几个主要特点:

  • 其内部实现是采用非线性的二叉树结构,具体的说是红黑树的结构原理实现的;
  • set 和map 保证了元素的唯一性,mulset 和mulmap 扩展了这一属性,可以允许元素不唯一;
  • 元素是有序的集合,默认在插入的时候按升序排列。

基于以上特点

  • 关联容器对元素的插入和删除操作比vector 要快,因为vector 是顺序存储,而关联容器是链式存储;比list 要慢,是因为即使它们同是链式结构,但list 是线性的,而关联容器是二叉树结构,其改变一个元素涉及到其它元素的变动比list 要多,并且它是排序的,每次插入和删除都需要对元素重新排序;
  • 关联容器对元素的检索操作比vector 慢,但是比list 要快很多。vector 是顺序的连续存储,当然是比不上的,但相对链式的list 要快很多是因为list 是逐个搜索,它搜索的时间是跟容器的大小成正比,而关联容器 查找的复杂度基本是Log(N) ,比如如果有1000 个记录,最多查找10 次,1,000,000 个记录,最多查找20 次。容器越大,关联容器相对list 的优越性就越能体现;
  • 在使用上set 区别于vector,deque,list 的最大特点就是set 是内部排序的,这在查询上虽然逊色于vector ,但是却大大的强于list 。
  • 在使用上map 的功能是不可取代的,它保存了“键- 值”关系的数据,而这种键值关系采用了类数组的方式。数组是用数字类型的下标来索引元素的位置,而map 是用字符型关键字来索引元素的位置。在使用上map 也提供了一种类数组操作的方式,即它可以通过下标来检索数据,这是其他容器做不到的,当然也包括set 。(STL 中只有vector 和map 可以通过类数组的方式操作元素,即如同ele[1] 方式)

unordered_map 和 unordered_set


C++11 新加入的 unordered_map 和 unordered_set 并不是红黑树的结构,而是采用了哈希表的结构,从而有了更快的查找效率,但是同时也是无序列的(unordered之意),而红黑树结构的map和set则看作是按键(key)有序的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值