STL—deque

deque介绍

双端队列 (deque)是一个容量可以动态变化,并且可以在两端插入或删除的序列式容器

deque逻辑模型:

deque迭代器:对结构体进行封装(主要含有四个指针成员属性cur,first,last,node)

想要使用deque需要引入头文件

#include<deque>

想要使用deque的一些泛型算法需要引入头文件

#include<algorithm>

deque的底层实现

deque底层是一个动态开辟的二维数组

deque没有容量大小这一说,deque表面上的连续是假象,底层是靠deque的迭代器将分段连续的空间串联起来的。其中deque的底层实现是靠下面的三部分实现的:

中控器(map)与缓冲区

(注意:这里的map不是STL中的关联式容器map)

因为deque的本质是由多个分段的连续空间构成,因此为了维持表面上连续的假象,需要一个中控器将所有的连续空间的地址组合保存起来,这样才能造成连续的假象,而中控器map其实是一个T**的指针,也就是一个二级指针

中控器map只是一小段的连续空间,而空间中存储节点指向的更大的连续空间称为缓冲区缓冲区才是deque的主存储体

deque的底层模型

deque迭代器

deque为了避免像vector一样 申请空间,拷贝数据,释放原有空间的繁琐操作,和为了将分段的连续空间组合起来,能够进行++找到下一个元素的位置等,因此底层由复杂的迭代器来实现

那么这样就将中控器,迭代器,缓冲区联系起来,即实现了空间连续的假象,也为deque的相关操作提供了可实行的方法。

例如:当我们设置一个缓冲区的大小时32个byte,需要存储20个int型的元素时,一个缓冲区可以存储8个元素,因此需要3个缓冲区来存储,也需要三个节点来将这三个空间链家起来,其中的迭代器如下图所示:

deque使用

初始化deque

deque<int> deq

初始化一个装有int类数据的容器,size为0

deque<int> deq(10)

初始化一个装有int类数据的容器,size为10,每个数据的默认值为0

deque<int> deq(5,9)

初始化一个装有int类数据的容器,size为5,每个数据初始化为9

deque<int> deq

deque<int> deq2(deq)

先初始化一个装有int类数据容器deq

再使用容器deq给装有int类数据容器deq2初始化

deque<int> deq(5,2)

deq2(deq.begin(),deque.begin()+3)

先初始化一个装有int类数据容器deq,size为5,每个数据初始化为2

再用容器deq的0-2下标数据(共3个)给装有int类数据容器deq2初始化,size为3

deque的一些内置函数

deque<int> deq;
deq.front();  //返回容器第一个节点的值
deq.back();   //返回容器最后一个节点的值
deq.begin();  //返回指向容器第一个节点的迭代器
deq.end();  //返回指向容器最后一个节点下一个位置(头节点)的迭代器
deq.clear();  //清空容器的值(size=0)
deq.empty();  //判空,如果容器为空则返回true,不为空返回false
deq.size();  //返回当前节点个数
deq.resize(size_t newsize,T c = T());  //重置deque的大小(含元素个数),多出来的空间用c填充
deq[n];  //返回deque上n位置上的元素

//使用less和greater需要引入头文件
#include<functional>
deq.sort(less<int>())  //将容器从小到大排序
deq.sort(greater<int>())  //将容器从大到小排序

deque迭代器iterator的使用

deque<int> deq(5,2)

deque<int>::iterator it = deq.begin()

初始化一个装有整形数据的容器deq,size=5,每个数据初始化为2

初始化指向int类数据的迭代器it,并指向deq的第一个节点

it.begin()

返回指向第一个节点的迭代器

it.end()

返回指向最后一个节点下一个节点的迭代器

it.rbegin()

返回指向最后一个节点前一个节点的迭代器

it.rend()

返回指向第一个节点前一个节点的迭代器

deque增删查改

增:

void push_front( const T val ):头插

void push_back( const T val ):尾插

iterator insert( iterator pos,const T val ):在pos位置之前插入数据

pos:指向要插入的位置的迭代器

val:要插入的值

返回值:指向新插入元素的迭代器

删:

void pop_front():头删

void pop_back():尾删

iterator erase( iterator pos ):删除pos位置的元素

pos:指向删除位置的迭代器

返回值:删除元素下一个元素的迭代器

查:

iterator find( iterator begin,iterator end,const T val ):在begin到end范围区间内查找值为val的元素,并返回指向此元素的迭代器

begin:查找范围的起始位置的迭代器

end:查找范围末尾的迭代器

val:查找的值

返回值:如果有此值-》返回指向此值的迭代器

如果没有-》返回容器的end()

改:

直接使用下标访问去修改容器中的值

deque的迭代器失效问题

插入

头插与尾插:

  1. 当中控器map还有空间时:头插与尾插不会导致迭代器失效

  1. 当中控器map已经满的时候:头插与尾插会导致重新分配空间(申请空间,拷贝数据,释放旧空间),此时会导致容器所有迭代器失效

其他部分插入

使用insert在其他地方插入时,会导致元素的挪移,因此会导致迭代器失效

删除

头删与尾删

头删和尾删只会导致被删除节点的迭代器失效

其他部分删除

使用erase去删除其他元素,会导致元素挪移,因此会导致迭代器失效

如何避免迭代器失效:

在使用insert和erase时,用迭代器去接收保存它们的返回值

deque的优缺点

优点:

可以随机访问元素[]

头部尾部的操作时间复杂度为O(1)

缺点:

遍历容器效率非常低

deque的使用场景

当我们只关心头部和尾部的操作,而不去遍历以及对中间数据的操作时,我们采用deque

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逐梦的白鹰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值