C++序列式容器vector,deque,list

5 篇文章 0 订阅

vector,deque,list定义于namespace std中,这三者是STL的序列式容器,也就是元素的位置和你置入元素的方式顺序有关系,三者在存储方式上有很大不同,处于程序运行效率,不同的存储方式,也就提醒我们在不同的应用场景中我们应该选择哪种容器。下面是三者的存储结构示意图:
如图1 vector的存储示意图所示,vector采用动态数组的方式存储元素,一个vector当前所拥有的内容空间可能要比它实际存储的元素的数量要多,如图1中的E表示实际存储的元素,后面表示待利用的空间,等待利用的空间用完之后,所有的元素会被拷贝到新的更大的空间中,这个空间可能是原来的空间的两倍或者其他根据具体的实现而定,可能会出现调用构造函数或拷贝构造函数的次数比我们实际存入的元素数量要多,主要是因为分配空间时vector会采用默认构造函数初始化内存空间,以及拷贝到新的内存空间中会调用。vector在插入元素时,一般插入到末尾,如果插入到前面会把插入位置之后的元素全部后移一个位置,如果元素过多可能效率太低。
这里写图片描述
如图2 deque的存储示意图所示,deque采用内存块对元素进行存储,当一个内存块存满时会分配下一个内存块,从图上我们也可以看到,deque可以从前从后进行内存块的分配,也就是可以从前从后进行元素的插入和删除。
这里写图片描述
如图3 list的存储示意图所示,list通过双向链表实现,可以实现任意位置的快速插入,但要查找满足某个条件的元素可能就要一次遍历链表了,链表可能更合用于插入频繁,查找较少的应用场景中。
这里写图片描述

访问元素时我们应该注意的事项:

  1. 对于vector而言,可以通过索引或者at成员函数对其中的元素进行访问,如下:

    c.at(index) //返回index所标识的元素,不进行index的范围检查,但当index越界时会抛出out_of_range异常
    c[index] //返回index所标识的元素,不进行index的范围检查,越界结果不可知
    c.front() //返回第一个元素,但不检查元素是否存在,越界结果不可知
    c.back() //返回最后一个元素,也不进行元素存在性检查,越界结果不可知

    提高vector性能的建议:

    (1). 在向量的尾端进行元素的插入和删除
    (2). 根据自己的需求,一开始就分配比较大的容量
    (3). 安插元素时,可以通过一次性插入多个元素,如:vec.insert(pos, n, elem);

  2. 对于deque而言,deque和vector相比具有如下优点

    (1).两端都可以插入元素
    (2).存取元素时,由于结构原因,指针或迭代器在移动的时候需要有某些转换的间接过程,所以指针和迭代器的动作会稍慢。
    (3).迭代器需要在不同内存块之间跳转,所以必须是特殊的智能指针,非一般指针。
    (4).在队内存区块大小有限制的系统中,由于vector的元素是只能存储于一个内存块中,而deque的元素存储于多个块中,所以,deque的max_size()会更大一些。
    (5).deque不必在重新分配内存时复制所有的元素。
    同时,deque也可以可以通过索引或者at成员函数对其中的元素进行访问,如下:

    c.at(index) //返回index所标识的元素,不进行index的范围检查,但当index越界时会抛出out_of_range异常
    c[index] //返回index所标识的元素,不进行index的范围检查,越界结果不可知
    c.front() //返回第一个元素,但不检查元素是否存在,越界结果不可知
    c.back() //返回最后一个元素,也不进行元素存在性检查,越界结果不可知

  3. list的内部结构和vector,deque的内部结构截然不同,list于vector和deque相比具有如下不同:
    (1).不支持随机存取,
    (2).在任何位置上,安插移除元素都非常快,
    (3).安插元素到任何位置都会导致references,pointers,iterators失效。而vector只有在尾部插入时,才不会导致references,pointers,iterators失效。而deque只有在收尾插入时,才不会导致references,pointers,iterators失效。
    (4).list不支持随机存储,不提供下标操作,也不提供at。
    (5).相对于vector和deque提供了一些变动性操作:

    L.unique(); //如果存在若干相邻而数值相等的元素,就一处重复元素。
    L.unique(op); //如果存在若干相邻的重复元素,使op返回true,则移除重复元素。
    L.splice(pos, L2);//将L2中的所有元素移动到L中,pos迭代器之前。
    L.splice(pos, L2, L2pos);//将L2中L2pos所指位置上的元素,移动到L中的pos位置上,L和L2可以相同。
    L.splice(pos, L2, L2beg, L2end);//将L2中[ L2beg, L2end]区间内的元素,移动到L内的pos之前。
    L.sort(); //以operator<为准则,对L内的元素进行排序。
    L.merge(L2); //在L和L2都已经有序的情况下,将L2中的所有元素,归并到L中,并且保证L仍有序。
    L.merge(L2, op);//在L和L2都是包含op的原则下的有序容器,将L2的所有元素转移到L中,并且保证L仍有序。
    L.reverse();//将所有的元素取反。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值