C++ STL中vector、list、deque顺序容器使用介绍

1、简介

容器分为顺序容器和关联容器,顺序容器提供了控制元素存储和访问顺序的能力,这种顺序不依赖于元素的值,而是与元素加入时的位置相对应。

2、顺序容器类型

顺序容器有以下几种

vector vector是可变大小数组,每个元素在内存上是连续的。支持快速随机访问,在尾部插入或者删除可能很慢。连续存储结构
deque 双端队列,支持快速随机访问。在尾部插队/删除都很快。deque双端数组结构,容器内部有一个中控器和缓存区,容器的数据放在缓存区中,中控器维护每个缓存区的地址,且该地址连续,类似vector。连续存储结构
list 双向链表。只支持双向顺序访问,,在list中任何位置进行插入/删除操作速度都很快。非连续存储结构
forward_list 单向链表。只支持单向顺序访问。在链表的任何位置进行插入/删除操作速度都很快。
array 固定大小数组。支持快速随机访问。不能添加或删除元素。
string 与vector相似的容器,但专门用于保存字符。随机访问快,在尾部添加/删除速度很快。

3、常用容器比较 

常用的顺序容器有vector、list、deque,在不同的使用场景下选择不同的容器可以提高程序的速度。选择容器时需要考虑:频繁插入/删除还是频繁随机访问,上面2介绍的表格中已经给出了总结。现将每个这三种容器再扩展分析如下:

(1)vector:vector在内存上是顺序存储的,也就是vector存储的元素内存区域必须是连续的。vector存储元素时,会预先分配一个一块比实际存储元素大的内存空间,这个空间叫做capacity,所以经常可以看到capacity大于容器的size值,查资料说是capacity的大小是size的2倍,这跟编译器有关的,不同的编译器大小关系是不一样(如不同的VS版本)。当往容器中插入元素时,如果容器中已没有空间存储新元素,则vector必须重新分配空间,且空间必须时连续的,这时vector需要做的操作为:申请新的空间-》赋值vector旧的元素-》插入新元素-》释放vector旧的元素空间。所以插入删除速度较慢,但随机访问很快,时间复杂度:O(1)。开辟空间连续,不易造成内存碎片。

迭代器影响:插入和删除会导致原先的迭代器失效,删除时,当前迭代器需要重新赋值,否则会造成当前迭代器失效。

(杂谈:在压测程序内存时,会检测内存的涨幅曲线,有时我们会看到内存曲线先涨,后降低平稳,有可能就跟vecotr容器申请空间有关)

(2)list:list是非连续存储结构,有双向链表结构体,每个元素有数据域和指针域,双向链表的结构如下:

扫描二维码关注公众号,回复: 14913735 查看本文章

 上面的图来源于双向链表 - 数据结构和算法教程 (yiibai.com)

 在插入新数据时,list不需要重新分配空间,只需要找一块内存进行数据的添加即可,但不支持随机访问,访问时的时间复杂度是O(n),动态开辟不连续的空间,容易造成内存碎片。

迭代器影响:插入和删除不会导致迭代器失效,删除只会导致当前迭代器失效。

(3)deque:deque (double-ended queue,双端队列)是一种具有队列的性质的数据结构。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。duque的内存结构如下:

 上面的图来源于deque容器详解_月光晒了很凉快的博客-CSDN博客_deque

 从上面的图可以看出,deque占用的内存较大。

 4、容器使用选择

(1)需要频繁随机访问,选vector。

(2)若插入数据元素大小已知,(通过设置容器大小)可选择vector。

(3)需要频繁在容器头尾进行插入和删除,且需要频繁随机访问,可选deque。

(4)需要频繁在容器任何位置插入和删除,可选list。

(5)若需要频繁插入容器任何位置,且要随机访问,也可选deque。

目前计算机的性能很高,当数据量不大时,性能差距是不大的,可以优先选择vector。

关于容器的比较有一篇博文介绍的也不错,可参考:C++三种容器:list、vector和deque的区别_戎·码一生的博客-CSDN博客_c++ deque list

猜你喜欢

转载自blog.csdn.net/hanxiaoyong_/article/details/126420972