c++容器

本文详细解析了C++容器的概念、分类及特性,重点介绍了vector、list、deque、map和set的使用场景与特点。通过实例展示了如何在不同需求下选择合适的容器类型,以及它们之间的性能对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   终于是把C++ Primer翻完了,称不上看完,好多不会的跳过了,以前看到容器这章就看不下去了,这次有进步,直接看完了,对容器也没有特别深的理解,仅从表面上有了些概念,想记录一下,以后再逐步深入。

    容器是容纳特定类型对象的集合,这种“对象”还包含一系列处理“其它对象”的方法。我从数组的角度去理解,但是容器又不像数组那样简单,容器比数组有更复杂的数据结构,还实现了其他比数组复杂的操作。在我的理解上,vector像是数组,list像是链表,map像是哈希表,但是容器中存放的内容和功能更强大。比如,顺序容器的resize()可以调整容器的大小,clear()可以清除容器中的所有元素,数组在这些操作上面就比较力不从心。容器有顺序容器和关联容器。

    顺序容器的各元素之间有顺序关系,是一种线性结构的可续群集。每个元素有固定的位置,插入和删除可以改变这个位置,这个位置和元素本身无关,和操作的时间有关。顺序容器不根据元素的特点排序而根据元素操作的逻辑顺序排序。

    vector,线性顺序结构,类似于数组,不过数组大小需要预先指定,vector大小不必预先指定,可以扩展,所以可以将vector看作是功能更强大的动态数组。(不过动态扩展vector时非常消耗性能,尽量在创建vector时就指定大小)

vector<int > v1;//创建一个可以存放int型的容器

vector特点

(1) 指定一块如同数组一样的连续存储,但空间可以动态扩展。即它可以像数组一样操作,并且可以进行动态操作。通常体现在push_back() pop_back() 。

(2) 随机访问方便,它像数组一样被访问,即支持[ ] 操作符和vector.at()

(3) 节省空间,因为它是连续存储,在存储数据的区域都是没有被浪费的,但是要明确一点vector 大多情况下并不是满存的,在未存储的区域实际是浪费的。

(4) 在内部进行插入、删除操作效率非常低,这样的操作基本上是被禁止的。Vector 被设计成只能在后端进行追加和删除操作,其原因是vector 内部的实现是按照顺序表的原理。

(5) 只能在vector 的最后进行push 和pop ,不能在vector 的头进行push 和pop 。

(6) 当动态添加的数据超过vector 默认分配的大小时要进行内存的重新分配、拷贝与释放,这个操作非常消耗性能。 所以要vector 达到最优的性能,最好在创建vector 时就指定其空间大小。

    list,线性链表结构,类似于链表,数据由结点构成,每个结点都包含一定的数据信息和指向后继结点的指针,存储在非连续的内存中,初始化时无需指定大小。

list<string> slist;//定义一个存放string类型的list容器

list特点:

(1)不使用连续的内存空间
(2)可以在任意位置进行插入删除
(3)不能进行随机访问
(4)比vector占用更多内存

    deque:双端队列,可在两端方便的进行插入删除,但在中间插入删除元素仍比较费劲;可以随机访问,但是不像vector那样存储在连续的内存空间中,采用多个连续的存储块,并且在一个映射结构中保存对这些块及其顺序的跟踪。

deque 的特点
(1) 
随机访问方便,即支持[ ] 操作符和vector.at() ,但性能没有vector 好;
(2) 
可以在内部进行插入和删除操作,但性能不及list ;
(3) 
可以在两端进行push 、pop ;

容器的选择:

(1)如果程序要求随机访问元素,则使用vector或deque

(2)如果程序必须在容器的中间位置插入或者删除元素,则使用list

(3)如果程序不是在容器首部或尾部插入或删除元素,则使用deque

(4)如果只需要在读取输入时在容器中间位置插入元素,然后需要随机访问,则可考虑在输入时将元素读入一个list容器,然后对此容器排序,使之适合顺序访问,然后将排序后的list容器复制到一个vector容器。

 



关联容器是非线性的树结构,各元素没有顺序,不像顺序容器那样按元素操作的逻辑顺序排序。不过关联容器可以根据元素进行排序,可以根据元素的特点来获取元素。

    关联容器和顺序容器的本质差别在于:关联容器通过键存储和读取元素,而顺序容器通过元素在容器中的位置顺序存储和访问元素。

    两个基本的关联容器是map和set,map的元素以键-值(key-value)形式组织,键用做元素在map中的索引,一般键都会是有一定线性顺序,值表示所存储和读取的数据;set仅包含一个键,并有效的支持关于某个键是否存在的查询

    map和set不允许有重复的键,map中一个键只能对应一个值,set中不能有重复的键;map和set中的值均不能修改,这点和顺序容器有区别!multimap中允许一个键对应多个值,multiset中允许一个键多次出现。

map容器:

map<k,v> m;//创建一个名为m的空map对象,其键和值的类型分别为k和v

在map中添加元素:map<string,int> word_count;//创建一个map

 word_count["Anna"]=1;

这两条语句:首先在容器word_count中查找键位Anna的元素,因为创建的容器为空,所以不可能找到,没有找到,将会新建一个键-值对插入到word_count中,键是string类型,保存Anna;值先进行初始化,读取新插入的元素,值为1,故将值赋为1.

set容器:

set容器是单纯的键的集合,当想知道一个值是否存在时,使用set容器是最好不过了(如,一个公司在谈接一笔订单时,就可以在自己的黑名单中查看对方公司是否存在,此时用set容器就很合适)。

set不支持下标操作,在set中插入元素:set<string> set1;//创建一个set容器

    set1.insert("the");//将"the"插入到容器

从set中获取元素,可使用find()运算;如果判断某个元素是否存在,可使用count(),对于set,count()的返回值只能是1(该元素存在),0(该元素不存在)。

map用于字典,电话本等需要键-值对应的情形,set用于查找某个值,在文本处理方面多用,比如要设置黑名单等等。


关联容器与顺序容器的比较

(1)关联容器对元素的插入删除快于vector慢于list,vector是顺序存储,关联容器是链式存储,并且是二叉树结构,改变一个元素涉及到的移动多与list。

(2)关联容器对元素的检索慢于vector快于list。vector O(1),list O(n),关联 O(logn)

(3)set内部排序,使set的查询很方便

(4)map的功能不可取代,键-值存储方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值