C++ STL容器适用情况的说明

各种容器的特性

vector

典型的序列容器,C++标准严格要求次容器的实现内存必须是连续的,唯一可以和标准C兼容的stl容器,任意元素的读取、修改具有常数时间复杂度,在序列尾部进行插入、删除是常数时间复杂度,但在序列的头部插入、删除的时间复杂度是O(n),可以在任何位置插入新元素,有随机访问功能,插入删除操作需要考虑。

deque

序列容器,内存也是连续的,和vector相似,区别在于在序列的头部插入和删除操作也是常数时间复杂度,可以在任何位置插入新元素,有随机访问功能。

list

序列容器,内存是不连续的,任意元素的访问、修改时间复杂度是O(n),插入、删除操作是常数时间复杂度,可以在任何位置插入新元素。

set

关联容器,元素不允许有重复,数据被组织成一棵红黑树,查找的速度非常快,时间复杂度是O(logN)

multiset

关联容器,和set一样,却别是允许有重复的元素,具备时间复杂度O(logN)查找功能。

map

关联容器,按照{键,值}方式组成集合,按照键组织成一棵红黑树,查找的时间复杂度O(logN),其中键不允许重复。

multimap

map一样,区别是键可以重复,比如两种水果,苹果和橘子,价格是一样的。这时候multimap就有用武之地了。

容器的分类

连续内存的容器:这种类型容器包含vectordeque。特点是在一块连续的内存块上存放数据,所以有数据插入和删除的时候,如果不是在序列的或者两端那么花费的代价是非常大的,因为需要保证连续内存,同时给新元素腾出空间或者填充删除元素的空间,如果存储的是复杂结构的话就要花费大量的时间进行拷贝操作(可以存储复杂结构的指针来弥补这个缺陷,这个讨论在另个总结中进行)。

基于节点的容器:这类容器是剩余的几个listsetmultisetmapmultimap.这类容器中的数据是分别存储在不同的内存块中,可能连续也可能不连续(一般不认为是连续的),这样的容器在插入删除元素的时候修改的只是节点的指针,这样的消耗是非常小的。

在使用这些容器时,需要考虑的因素

1.需要大量添加新元素

vector在大量添加元素的时候问题最大,因为他的一种最常见的内存分配实现方法是当前的容量(capacity)不足就申请一块当前容量2倍的新内存空间,然后将所有的老元素全部拷贝到新内存中,添加大量元素的时候的花费的惊人的大。如果由于其他因素必须使用vector,并且还需要大量添加新元素,那么可以使用成员函数reserve来事先分配内存,这样可以减少很多不必要的消耗。

list对这种情况的适应能力就非常好,都是常数时间的插入消耗。deque前面说过了,他是vectorlist的折衷形式,内存不够了就申请一块新的内存,但并不拷贝老的元素。

2.查找速度

这个因素主要取决于算法,而算法最终是作用在容器中元素上的,所以这里的查找速度指的是容器能够达到的最好查找效率。

对于序列容器需要分两种情况,区分依据是元素是否排序,1)对于已经排序的序列容器,使用binary_searchlower_boundupper_boundequal_range可以获得对数时间复杂度的查找速度(O(logN));2)而未排序的序列容器二分查找肯定是用不了,能达到的最好的时间复杂度是线性的(O(n))

对于关联容器,存储的时候存储的是一棵红黑树(一种更为严格的平衡二叉树,文档最后有介绍),总是能达到对数时间复杂度(O(logN))的效率,因为关联容器是按照键值排好序的。

3.是否是连续内存

连续内存的容器有个明显的缺点,就是有新元素插入或老元素删除的时候,为了给新元素腾出位置或者填充老元素的空缺,同一块内存中的其他数据需要进行整体的移位,这种移位的拷贝代价有时是非常巨大的。标准容器中的vectordeque是连续内存的,其中vector是完全连续内存,而dequevectorlist的折衷实现,是多个内存块组成的,每个块中存放的元素连续内存,而内存块又像链表一样连接起来。

所以需要考虑在操作的过程中是否有在任意位置插入元素的需求,有这种需求的话尽量避免使用连续内存的vectordeque

 

4.元素的排序

序列容器中的元素不会自动排序,程序员插入什么顺序内存中就是什么顺序,而关联容器不是这样的,他会以自己的键值按照某种等价关系(equivalence)进行排序。所以默认情况下序列容器中的元素是无序的,而关联容器中的元素是有序的。

所以容器在遍历元素的时候序列容器输出的顺序和插入的顺序式一致的,关联容器就不一定了。


各个容器的优缺点

1.Vector的数据模型就是数组。

优点:内存和C完全兼容、高效随机访问、节省空间

缺点:内部插入删除元素代价巨大、动态大小查过自身容量需要申请大量内存做大量拷贝

2.List的数据结构模型是链表

优点:任意位置插入删除元素常量时间复杂度、两个容器融合是常量时间复杂度

缺点:不支持随机访问、比vector占用更多的存储空间

3.Deque的数据模型是数组和链表的折衷:

优点:高效随机访问、内部插入删除元素效率方便、两端push pop

缺点:内存占用比较高

4.Mapsetmultimapmultiset的数据结构模型是二叉树(红黑树)

优点:元素会按照键值排序、查找是对数时间复杂度、通过键值查元素、map提供了下标访问

综合考虑

1)如果需要随机访问,用vector

2)如果存储元素的数目已知,用vector

3)需要任意位置随机插入删除,用list

4)只有需要更多在容器的首部尾部插入删除元素,用deque

5)元素是复杂结构用list,也可以用vector存储指针(需要额外的精力去维护内存),看需求

6如果操作是基于键值,用set map

7如果需要经常的搜索,用mapset

8 map set的区别是map中的元素都是pair,同时map提供下标访问[] ,也是个陷阱

个人文库地址

http://wenku.baidu.com/p/helpylee

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ STL(Standard Template Library)是C++标准库中的一个重要组成部分,提供了一组数据结构和算法的模板类,可以大大简化C++程序的开发过程。STL包含了多个容器类,每个容器类都有其特定的特性和用途。 STL中的容器类主要分为序列容器和关联容器两大类。序列容器包括vector、list、deque和array,它们按照元素在容器中的位置进行存储和访问。关联容器包括set、multiset、map、multimap和unordered系列容器,它们按照键值进行存储和访问。 序列容器具有以下特性: 1. 动态大小:序列容器可以根据需要动态调整大小,可以在任意位置插入和删除元素。 2. 快速随机访问:序列容器中的元素可以通过索引快速访问,时间复杂度为O(1)。 3. 按顺序存储:序列容器中的元素按照插入的顺序存储,并保持元素的相对位置不变。 4. 支持迭代器:序列容器提供了迭代器,可以通过迭代器遍历容器中的元素。 关联容器具有以下特性: 1. 自动排序:关联容器中的元素按照键值自动排序,并且可以根据自定义的比较函数进行排序。 2. 快速查找:关联容器支持快速的查找操作,时间复杂度为O(log n)。 3. 不允许重复键值:set和map容器中的键值是唯一的,而multiset和multimap容器允许重复的键值。 4. 无序容器:unordered系列容器C++11引入的,它们使用哈希函数来存储和访问元素,查找操作的平均时间复杂度为O(1)。 总而言之,C++ STL提供了丰富的容器类,每个容器类都有其独特的特性和适用场景,可以根据具体需求选择合适的容器来存储和操作数据。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++——STL容器](https://blog.csdn.net/JAN6055/article/details/122758690)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [C++STL容器类详解](https://blog.csdn.net/Jinyizhi2233/article/details/131640448)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值