顺序容器简介

原文链接

顺序容器概述
所谓的顺序容器是指,在内存中数据存储有一定顺序。数据结构中的顺序容器有:可变数组、队列、数组、链表、栈。

vector:可变大小的数组。支持快速随机访问,在尾部之外插入或者删除元素可能会很慢
dque:双端队列,支持快速随机访问,在头尾位置插入/删除元素速度很快
list:双向连标,只支持双向顺序访问,在list中任何位置进行插入删除操作速度都很快
forward_list: 单向链表,只支持单向顺序访问,在链表任何位置插入删除元素速度很快
array: 固定大小的数组,支持快速随机访问,不能添加或者删除元素
string: 与vector容器类似,但专门用于保存字符,随机访问快。在尾部插入与删除速度快
c++ 标准库中的容器是经过精心优化设计过的。性能通常会是同类数据结构中最好的。现代c++ 程序应该使用标准库容器,而不是原始的数据结构(如内置数组)

通常使用vector 是最好的选择,除非你有很好的理由选择其他容器

如果两个迭代器满足以下两个条件,则这两个迭代器构成一个迭代器范围:

它们指向同一个容器中的元素,或者是容器最后一个元素之后的位置
我们可以通过反复递增begin 来到达end位置,换句话说,end不在begin之前
如果两个迭代器构成一个迭代器范围


每个容器都定义了多个类型,我们已经使用了其中的3种:size_type、iterator、const_iterator

除了正向的迭代器,容器库还提供了反向遍历容器的迭代器,反向迭代器就是一种反向遍历容器的迭代器。与正向迭代器相比各种操作的含义也都发生了颠倒。例如对一个反向迭代器执行++操作,会得到上一个元素。

begin 和 end 成员
begin 和 end 操作生成一个指向容器中第一个元素和尾元素之后位置的迭代器范围。begin和end有多个版本。带r的版本返回反向迭代器,带c的版本返回const型迭代器

size: 返回容器中元素数目
empty: 当容器中元素数量为0时,返回true,否则返回false
max_size: 返回一个大于或者等于该类型容器所能容纳的最大元素数的值

顺序容器的操作
向顺序容器中添加元素
push_back:将内容追加到容器尾部
push_front: 将内容添加到容器的首部
insert: 在容器的特定位置插入0个或者多个元素,返回插入元素位置的迭代器
emplace_back、emplace_front、emplace: 这些函数是直接在容器内部进行元素构造,而上述函数是将内容进行拷贝。从效率上讲emplace 函数会高一些
使用这些操作时必须记得不同类型的容器使用不同的元素分配策略,而这些策略直接影响性能。

删除元素
pop_front: 删除首元素
pop_back: 删除尾元素
erase: 可以从容器中删除指定位置的元素,可以传入一个范围,删除指定范围内的元素
特殊的 forward_list 操作
在对forward_list 进行增删操作的时候,需要找到对应位置的前驱节点,而单向链表无法很容器的找到一个节点的前驱节点。因此对单向链表,提供了类似 insert_after、emplace_after、erase_after等操作

改变容器大小
可以使用resize 来增大或者缩小容器大小,如果是缩小容器大小,则指向被删除元素的迭代器、引用、指针都会失效

容器操作可能使迭代器失效
在向容器中添加元素后:

如果容器是vector或者string,且存储空间被重新分配,则指向容器的迭代器、指针都会失效。如果存储空间未重新分配,指向插入位置之前的迭代器、指针、引用仍然有效,但是指向插入位置之后元素的迭代器、指针和引用将会失效
对于deque,插入到首尾位置之外的任何位置都会导致迭代器、指针和引用失效。如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效
对于list和forward_list,指向容器的迭代器、指针和引用仍然有效
删除一个元素后,指向原来被删除元素的迭代器、指针和引用都会失效。

对于forward_list 和list来说,指向容器其他位置的迭代器、引用和指针仍然有效
对于deque,如果在首尾之外的任何位置删除元素,那么指向被删除元素以外的其他元素的迭代器、引用和指针也会失效。如果是删除deque的尾元素,则尾后迭代器也会失效。但是其他迭代器、引用和指针不受影响,如果删除首元素,这些也不会受到影响
对于vector和string,指向被删除元素之前元素的迭代器、引用和指针仍然有效
删除元素时尾后迭代器总是会失效

使用insert插入元素后可以保存返回的迭代器,然后用该迭代器进行迭代可以保证迭代器有效

不要保存end返回的迭代器

vector 容器是如何增长的
为了支持快速随机访问,vector 将元素连续存储。如果往容器中添加一个新元素时,发现容器空间已经不够了,就需要重新分配空间。并将已有元素逐一拷贝到新的内存空间中,然后添加新元素。

为了避免这种代价,标准库实现者采用了可以减少容器空间重新分配次数的策略。当不得不获取新的内存空间时,vector和string的实现通常会分配比新的空间需求更大的内存空间

vector和string也提供了一些成员函数,允许我们与它的实现中内存分配部分互动。

capacity: 告诉我们容器在不扩张内存空间的情况下可以容纳多少个元素
reserve: 允许我们同志容器它应该准备保存多少个元素
一般来讲,vector 的实现采用的策略似乎是在每次需要分配新内容空间时将当前容量翻倍

额外的string操作
除了顺序容器共同的操作之外,string类还提供了一些额外的操作。

这些操作中的大部分要么是提供string类和C风格字符串之间的互相转换,要么是增加了允许我们用下标代替迭代器的版本。

substr: 返回一个string,它是原始string的一部分或者全部的拷贝
可以使用insert、erase、assign 来改变字符串的内容
append可以在字符串尾部添加一个新字符串; replace 进行查找替换

compare 函数
compare函数用于比较两个大小字符串,与C标准库中的strcmp类似

数值转化
to_string: 将数值数据转化为字符串
stod: 将字符串转化为double
stof: 将字符串转化为float
stoi: 将字符串转化为int
stol: 将字符串转化为long
stoul: 将字符串转化为 unsigned long
stoll: 将字符串转化为 long long
stoull: 将字符串转化为 unsigned long long
stold: 将字符串转化为 long double
容器适配器
适配器是标准库提供的一组概念,能使某种事物的行为看起来像另一种事物一样。一个容器适配器接受一种已有的容器类型,使其行为看起来像另一种事物一样

标准库提供了三种适配器: stack、queue、priority_queue(优先级队列)

所有的适配器都要求容器具有添加和删除元素的能力。

stack 只要求类型容器具有 push_back、pop_back 操作因此可以使用除了array 和 forward_list 之外的任何容器类型来进行构造

queue 要求容器类型具有 back、push_back、front、pop_back 因此它可以构造在list 或者deque之上但不能基于vector 构造;
priority_queue 要求容器类型具有push_back、front、pop_back之外还要求容器具有随机访问的能力,所以它必须构造在vector之上
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值