C++ STL容器比较--读《C++标准程序库》总结

array
array 是固定大小的顺序容器,它们保存了一个以严格的线性顺序排列的特定数量的元素,支持随机读改 O(1),快速访问。
方法参考:https://en.cppreference.com/w/cpp/container/array

Vectors
Vectors 是一种有序群集,vector支持随机存取,因此只要知道位置,你可以在常数时间内存取任何一个元素。Vector的迭代器是随机存取迭代器,所以任何一个STL算法都可以凑效。
在末端附加或删除元素时,vector的性能相当好,可是如果在前端或中部安插或删除元素,性能就不怎么样了,因为操作点之后的每一个元素都必须移到另一个位置,而每一次移动都得调用assignment(赋值)操作。
关于性能,一下情况你可以预期安插操作和移除操作会比较快些;
1、在容器尾部安插或移除元素
2、容量一开始就够大
3、安插多个元素时,调用一次比调用多次来的快,安插元素移除元素,都会使作用点之后的各元素的reference、pointers、iterators失效。如果安插操作甚至引发内存重新分配,那么该容器身上的所有reference、pointers、iterators都会失效。

C++标准程序库并未明确要求vector的元素必须分布于连续的空间中。但是一份标准规格缺陷报告显示,这个缺点将获得弥补。标准规格书中将明确保证上述论点。如此一来你可以确定对于vector V中任何一个合法索引1,以下表达式肯定为TRUE,
&V[i]==&V[0]+i
保证了这一点,任何地点只要你需要一个动态数组,你就可以使用vector,如
Std::vector<char> V;
V.resize(41);
Strcpy(&V[0],”HELLO,WORLD”);
Printf(“%s\n”,&V[0]);
不过,这么使用vector你必须小心,例如确保上述vector的大小足以容纳所有数据,如果你用的是C-String,记住最后有个’\0’。
Vector 方法可参考链接:https://en.cppreference.com/w/cpp/container/vector

Deques
采用动态数组来管理元素,提供随机存取,并有着和vector几乎一模一样的接口,不同的是deques的动态数组头尾都开放,因此能在头尾两端进行安插和删除。如下图所示:

                                              

为了获得这种能力,deques通常实作为一组独立区块,第一区块朝着某方向扩展,最后一个区块朝着另一个方向扩展,如下图;

                                                             

Deques的能力,与vector不同deques在于以下几点;
1、两端都能快速安插元素和删除元素,这些操作可以在分期摊还的常数时间内完成。
2、存取元素时,deques的内部结构会多一个间接过程,所以元素的存取和迭代的动作会稍微慢一些。
3、迭代器需要在不同区块见跳转,所以必须是特殊的智能指针,非一般指针。
4、在对内存区块有所限制的系统中,deque可以包含更多元素,因为它使用不止一块内存。因此deque的max_size()可能更大。
5、deque不支持对容量和内存重分配时机的控制。特别注意的是,除了头尾两端,在任何地方安插或删除元素,都会导致指向deque元素的任何pointers、references、iterators失效。不过,deque的内存分配由于vector,因为其内部结构显示,deques不必再内存重新分配时复制所有元素。
6、deque的内存块不在被使用时,会被释放。deque的内存是可以缩减的,根据具体实作版本确定。

与vector功能差不多如下几点:
1、在中段部分安插或删除元素时速度较慢,因为所有元素都需要移动以腾出或填补空间。
2、迭代器属于随机存取迭代器。
总之以下情形最好采用deque:
1、你需要在两端安插和移除元素(这是deque的拿手好戏)。
2、无需引用容器内的元素。
3、要求容器释放不再使用的元素
Vector与deques的接口几乎一样,所以如果无需什么特殊性质,两者都可试试。
deque 方法可参考链接:https://en.cppreference.com/w/cpp/container/deque

List
List 使用一个双向链表来管理元素,如下图所示:

              

List的能力:
1、List的内部结构和vector或deque 截然不同,所以在几个主要方面与前述二者存在明显差别;
2、List不支持随机存取,如果你需要区地5个元素,就得顺着窜链一一爬过前面4个元素。所以,在list中随机遍历任意元素,是很缓慢的行为。
3、任何位置上(不只是两端)执行元素的安插和移除都非常快。因为无需移动仍和其他元素,实际上内部知识进行了一些指针操作而已。
4、安插和删除动作并不会造成指向其他各元素的各个pointers、reference、iterators失效。
5、List对异常的有着这样的处理方式:要么操作成功,要么什么都不发生。

List与vector和deques的不同:
1、由于不支持随机存取,list既不提供下标操作,也不提供at().
2、List并未提供容量、空间重置分配等操作,因为全无必要。每个元素都有自己的内存,在被删除之前一直有效。
3、List提供了不少特殊的成员函数,专门用于移动元素,较之同名的STL通用算法,这些函数执行起来更快,因为它们无需拷贝或移动,只需调整若干指针即可。
std::list 方法可参考链接:https://en.cppreference.com/w/cpp/container/list

Set和Multisets
Set和Multisets会根据特定的排序准则,自动将元素排序。两者的不同之处在于Multisets允许重复,而Set不允许。

 Set和Multisets的能力:
和所有的关联容器类似,两者的内部结构皆为平衡二叉树,结构如下:                                                                                                                                                

基于自动排序的优点,使得二叉树于搜寻元素时具有较好的性能,其搜寻函数算法具有对数复杂度。在拥有1000个元素的set和multisets中搜寻元素,二叉树的平均搜寻时间是线性搜寻(STL算法执行)时间的1/50 。
其缺点是:
1、不能直接改变元素,因为这样会打乱原有的顺序。要改变的话则要先删除原有的元素,再插入新元素。
2、不提供用来直接存储元素的任何操作函数,只能通过迭代器。

Maps和Multimaps
Maps和Multimaps将key/value当做元素,进行管理。它可根据key的排序准则自动将元素进行排序,Multimaps运行重复,Maps不允许。

 和 Set/ Multisets关联容器类似,两者的内部结构皆为平衡二叉树,典型情况下Set/ Multisets/maps/multimaps具有相同的数据结构,可以把Set/ Multisets视为特殊的map和multimaps,只不过set的key和value为同一对象,因此它们四者的能力和操作函数一样。当然它们的元素是key/value pair,其次map可作为关联式数组来运用,结构如下: 

 

方法参考:https://en.cppreference.com/w/cpp/container/map

附录:
容器之间的比较

容器

底层数据结构

时间复杂度

有无序

可不可重复

其他

array

数组

随机读改 O(1)

无序

可重复

支持快速随机访问

vector

数组

随机读改、尾部插入、尾部删除 O(1)
头部插入、头部删除 O(n)

无序

可重复

支持快速随机访问

list

双向链表

插入、删除 O(1)
随机读改 O(n)

无序

可重复

支持快速增删

deque

双端队列

头尾插入、头尾删除 O(1)

无序

可重复

一个中央控制器 + 多个缓冲区,支持首尾快速增删,支持随机访问

stack

deque / list

顶部插入、顶部删除 O(1)

无序

可重复

deque 或 list 封闭头端开口,不用 vector 的原因应该是容量大小有限制,扩容耗时

queue

deque / list

尾部插入、头部删除 O(1)

无序

可重复

deque 或 list 封闭头端开口,不用 vector 的原因应该是容量大小有限制,扩容耗时

priority_queue

vector + max-heap

插入、删除 O(log2n)

有序

可重复

vector容器+heap处理规则

set

平衡二叉树

插入、删除、查找 O(log2n)

有序

不可重复

 

multiset

平衡二叉树

插入、删除、查找 O(log2n)

有序

可重复

 

map

平衡二叉树

插入、删除、查找 O(log2n)

有序

不可重复

 

multimap

平衡二叉树

插入、删除、查找 O(log2n)

有序

可重复

 

hash_set

哈希表

插入、删除、查找 O(1) 最差 O(n)

无序

不可重复

 

hash_multiset

哈希表

插入、删除、查找 O(1) 最差 O(n)

无序

可重复

 

hash_map

哈希表

插入、删除、查找 O(1) 最差 O(n)

无序

不可重复

 

hash_multimap

哈希表

插入、删除、查找 O(1) 最差 O(n)

无序

可重复

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值