c++顺序容器详解

顺序容器:

c++提供的容器分为顺序容器和关联容器。顺序容器也称为序列式容器。序列式容器按元素插入的顺序存储元素,这些元素可以进行排序,但未必是有序的。

1、array

  1. array内部是一个固定数组,是连续存储结构,定义时便要指定大小(如:array<int,10> a),随机访问(operator[ ]和vetor.at( ))效率很高
  2. array分配内存的位置取决于定义的位置和方式(如定义为全局变量或局部静态变量,则在全局/静态存储区上分配内存)。
  3. array不支持添加和删除元素等改变容器大小的操作

2、vector

  1.  vector内部是一个建立在自由存储区上的连续存储结构,所以随机访问(operator[ ]和vetor.at( ))效率很高
  2. vector定义时会默认分配一个非常大的连续内存空间进行存储,可用capacity()来返回该空间的大小。
  3. vector与数组类似,但是当vector内部分配的内存空间不够用时,会自动重新分配一块更大的空间进行扩充,而array扩充空间要程序员自己写。
  4. 在vector尾部插入删除元素时效率较高,而在其他地方进行插入删除操作效率很低,因为要进行元素的拷贝移动。只支持在尾部push和pop。

3、string

  1. 与vector相似的动态数组,专用来保存操作字符
  2. string内部是连续存储结构,随机访问效率高。
  3. 在string尾部插入删除元素时效率较高,而在其他地方进行插入删除操作效率很低,支持在尾部push和pop。

4、list

  1. list内部是一个双链表结构,每个元素都包括一个信息Info、一个前驱指针pre、一个后驱指针post,所以是一个非连续的存储结构
  2. 因为list内元素的非连续存储,所以不支持随机访问(operator[ ]和vetor.at( ))。
  3. 在list内进行插入删除操作时效率很高,只需新建元素后用指针维护元素间的关系,不需大量拷贝移动元素。可在两端进行push和pop。

5、forward_list

  1. forward_list内部是单链表结构,所以只支持单向顺序访问。
  2. 因为list内元素的非连续存储,所以不支持随机访问(operator[ ]和vetor.at( ))。
  3. 和list相似在任何位置进行插入删除操作时效率很高。可在头部进行push和pop,出于对效率的考虑,不提供在尾部的操作。
  4. forward_list是唯一一个在给定位置之后插入新元素的容器(如:insert_after、emplace_after、erase_after、splice_after),不提供size()操作。

6、deque

  1. deque内部是多个独立的连续存储块,提供了两级数组结构,第一级维护类似于vector的容器,第二级维护一级容器的首地址(相当于虚拟的连接多个连续存储块)。
  2. deque支持较为快速的随机访问,但是因为deque是两级结构,所以随机访问速度比vector稍慢一些
  3. deque第一个区块朝一个方向扩展,最后一个区块朝另一方向扩展。因为deque在前面和后面添加元素时都不需要移动其它块的元素,所以支持高效的首/尾端插入或删除操作,而在中间插入删除和vector一样效率较低。

 

比较:

容器头文件内部存储结构元素访问插入/删除操作效率迭代器失效
array<array>固定大小快速随机访问不支持插入/删除对象被销毁时失效
vector<vector>动态一维数组快速随机访问尾部高效插入/删除若引起内存重新分配,则全部迭代器失效;否则插入点/删除点之后的迭代器失效
string<string>只存储字符的动态数组快速随机访问
list<list>双向链表双向顺序访问任何位置高效插入/删除删除操作后指向被删除元素的迭代器失效
forward_list<forward_list>单向链表单项顺序访问
deque<deque>双端队列快速随机访问首尾高效插入/删除

在首部或尾部删除元素使指向被删除元素的迭代器失效;其他位置插入和删除时将使所有迭代器失效

 

选用容器的情况:

  1. 如果需要高效、灵活的内存管理,最好不使用array,一般情况下使用vector比较好。
  2. 如果需要随机访问操作,则使用vector或deque。
  3. 如果只需要在容器末尾插入/删除操作,则使用vector;如果只需要在容器首尾插入/删除操作,则使用deque;如果需要在容器中部插入/删除操作,则使用list或forward_list。
  4. 既需要随机访问,又需要随机插入/删除,则使用deque。
  5. 若空间开销比较重要时,则不使用list或forward_list。
  6. 只对字符进行存取操作时,使用string。

 

容器适配器:

  1. stack(栈),一种先进后出的数据结构,stack默认以deque为底部容器,通过push/pop接口对栈顶元素进行操作。
  2. queue(队列),一种先进先出的数据结构,queue默认以deque为底部容器,通过push向队尾压入元素,通过pop从队首弹出元素。
  3. priority-queue(优先队列),是一种拥有权值观念的queue,priority-queue以vector或deque为底部容器,支持随机访问。

 

容器操作:

具体每个容器可使用的操作函数可参考上述各容器特点

操作类型操作意义
构造C c默认构造函数,构造空容器
C c1(c2)构造c2的拷贝c1
C c(b,e)构造c,将迭代器b和e指定的范围内的元素拷贝到c(array不支持)
C c{a1,a2...an}列表初始化c
添加c.push_back(t)在容器c尾部添加值为t的元素。返回void 类型
c.push_front(t)

在容器c的前端添加值为t的元素。返回void 类型

c.insert(p,t)在迭代器p所指向的元素前面插入值为t的新元素。返回指向新添加元素的迭代器。
c.insert(p,n,t)在迭代器p所指向的元素前面插入n个值为t的新元素。返回void 类型
c.insert(p,b,e)在迭代器p所指向的元素前面插入由迭代器b和e标记的范围内的元素。返回 void 类型
大小操作c.size()返回容器c中元素个数。返回类型为 c::size_type
c.max_size()返回容器c可容纳的最多元素个数,返回类型为c::size_type
c.empty()返回标记容器大小是否为0的布尔值
c.resize(n)

调整容器c的长度大小,使其能容纳n个元素,如果n<c.size(),则删除多出来的元素;否则,添加采用值初始化的新元素

c.resize(n,t)调整容器c的长度大小,使其能容纳n个元素。所有新添加的元素值都为t
访问c.back()

返回容器 c 的最后一个元素的引用。如果 c 为空,则该操作未定义

c.front()返回容器 c 的第一个元素的引用。如果 c 为空,则该操作未定义
c[n]

返回下标为 n 的元素的引用。如果 n <0 或 n >= c.size(),则该操作未定义

c.at(n)

返回下标为 n 的元素的引用。如果下标越界,则该操作未定义

删除c.erase(p)删除迭代器p所指向的元素。返回一个迭代器,它指向被删除元素后面的元素。如果p指向容器内的最后一个元素,则返回的迭代器指向容器超出末端的下一位置。如果p本身就是指向超出末端的下一位置的迭代器,则该函数未定义
c.erase(b,e)删除迭代器b和e所标记的范围内所有的元素。返回一个迭代器,它指向被删除元素段后面的元素。如果e本身就是指向超出末端的下一位置的迭代器,则返回的迭代器也指向容器的超出末端的下一位置
c.clear()删除容器c内的所有元素。返回void
c.pop_back()删除容器c的最后一个元素。返回void。如果c为空容器,则该函数未定义
c.pop_front()

删除容器c的第一个元素。返回void。如果c为空容器,则该函数未定义

赋值c1 = c2删除容器 c1 的所有元素,然后将 c2 的元素复制给 c1。c1 和 c2 的类型(包括容器类型和元素类型)必须相同。
c1.swap(c2)交换内容:调用完该函数后,c1 中存放的是 c2 原来的元素,c2 中存放的则是 c1 原来的元素。操作数必须是相同类型的容器,而且所存储的元素类型也必须相同。
c.assign(b,e)重新设置 c 的元素:将迭代器 b 和 e 标记的范围内所有的元素复制到 c 中。b 和 e 必须不是指向 c 中元素的迭代器。
c.assign(n,t)将容器 c 重新设置为存储 n 个值为 t 的元素。

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值