STL_deque_stack_queue

Deque

deque容器(双端队列)
​deque是一种双向开口的分段连续线性空间(对外号称连续,使用者无法感知它是分段的)。deque支持从头尾两端进行元素的插入和删除。deque没有容量的概念,因为它是动态地以分段连续空间组合而成的。随时可以增加一段新的空间并连接起来。

deque用vector存储buffer,当前vector容量满了之后,vector二倍扩容,将原始数据拷贝到新数据的中段,
使得map 可以向两端扩容
在这里插入图片描述

deque 的迭代器

deque的迭代器是一个class

  • node指向控制中心map,当迭代器++或-- 时,可以跳转到另一个分段
  • first last指向当前所在buffer的头和尾,标记缓冲区的边界,当迭代器在走到当前buffer边界,下一步需要走到其他buffer(通过node)
  • cur 当前迭代器指向的元素
template<class T,class Ref,class Ptr,size_t BufSiz>
struct __deque_iterator
{typedef random_access_iterator_tag iterator_category; //1typedef T value_type;	//2typedef Ptr pointer;	//3typedef Ref reference;	//4typedef size_t size_type;	typedef ptrdiff_t difference_type; //5typedef T** map_pointer;typedef __deque_iterator self;T* cur;T* first;T* last;map_pointer node;...
};

deque源码

template<class T,class Alloc=alloc,size_t BufSiz=0>
class deque
{
public:typedef T value_type;typedef __deque_iterator<T,T&,T*,BufSiz> iterator;protected:typedef pointer* map_pointer; //T**iterator start;iterator finish;map_pointer map;size_type map_size;public:iterator begin(){return start;}iterator end(){return end;}size_type size(){return finish-start;}...
};

​ 为了维护这种整体连续的假象,带价就是迭代器的类型会比较复杂。即采用map(类型为T**)作为主控。map实际上是一块大小连续的空间,其中每一个元素,我们称之为node,每个node都指向了另一端连续线性的空间(上图的buffer),buffer才是deque真正存储空间的地方。

​ 其中buffer大小的确定:

/*
n不为0,传回n,buffersize由user确定
n为0,buffersize使用预设值,如果sz(sizeof(value_type))小于512,传回512/sz,否则就传回1
*/
inline size_t __deque_buf_size(size_t n,size_t sz)
{return n!=0?n:(sz<512?size_t(512/sz):size_t(1));
}

deque插入元素

deque::insert()插入函数首先判断传入迭代器的位置是处于容器前半部分还是后半部分,再插入进比较短的那一段。

deque::insert()

iterator inset(iterator position,const value_type& x)
{if(position.cur==start.cur){push_front(x);return start;}else if(position.cur==finish.cur){push_back(x);return finish}else{return insert_aux(position,x);}
}

若插入位置是容器首部,则直接push_front,位置是容器尾部,则直接push_back。其他情况则调用insert_aux方法:

template<class T,class Alloc,size_t BufSize>
typename deque<T,Alloc,BufSize>::iterator 
deque<T,Alloc,BufSize>::insert_aux(iterator pos,const value_type& x){difference_type index = pos-start; //安插点之前的元素个数value_type x_copy = x;if(index<size()/2){			//如果安插点之前的元素个数较少push_front(front());	//在最前端加入和第一元素同值的元素...copy(front2,pos1,front1); //元素搬移}else{					//安插点之后较少push_back(back());	//在尾端加入和最末元素同值的元素...copy_backward(pos,back2,back2); //元素搬移}*pos = x_copy;return pos;
}

deque如何模拟连续的空间:

reference operator[](size_type n){return start[difference_type(n)];
}reference front(){return *start;
}
reference back(){iterator tmp = finish;--temp;return *temp;
}size_type size()const{return finish-start;
}bool empty()const{return finish==start;
}

重要的操作符重载: -

  • 重载 判断两个迭代器之间的距离:
    两个迭代之间的buffer数量 + it1 到其尾部的长度 + it2 到其头部的长度
reference operator*()const{return *cur;
}pointer operator->()const{return &(operator*());
}//两根iterator之间的距离相当于  两根iterators之间的buffers的总长度+it1至其buffer尾部长度+it2至其buffer头部的长度
difference_type operator-(const self& x)const{return difference_type(buffer_size())*(node-x.node-1)+(cur-first)+(x.last-x.cur);
}
self& operator++(){++cur;if(cur==last){set_node(node+1); //跳到下一节点的起始节点cur = first;}return *this;
}self operator++(int){self tmp = *this;++*this;return temp;
}self& operator--(){--cur;if(cur==first){set_node(node-1); //跳到上一节点的尾节点cur = last;}return *this;
}self operator--(int){self tmp = *this;--*this;return temp;
}void set_node(map_pointer new_node){node = new_node;first = *node;last = first+difference_type(buffer_size());
}self& operator+=(difference_type n)
{difference_type offset = n+(cur-first);if(offset>=0&&offset<difference_type(buffer_size()))// 目标在同一buffer内cur +=n;else{// 目标不在同一buffer内difference_type node_offset = offset>0?offset/difference_type(buffer_size()):-difference_type((-offset-1)/buffer_size())-1;// 切换至正确的buffer内set_node(node+node_offset);// 切换至正确的元素cur = first+(offset-node_offset*difference_type(buffer_size()));}return *this;
}self operator+(difference_type n){self tmp = *this;return temp+=n;
}

queue和stack默认封装了 deque
调用deque种的函数

queue

在这里插入图片描述

template<class T, class Sequence=deque<T>>
class queue {
public:typedef typename Sequence::value_type value_type;typedef typename Sequence::size_type size_type;typedef typename Sequence::reference reference;typedef typename Sequence::const_reference const_reference;
protected:Sequence c;     // 底层容器,默认是deque<T>
public:bool empty() const { return c.empty(); }size_type size() const { return c.size(); }reference front() { return c.front(); }const_reference front() const { return c.front(); }reference back() { return c.back(); }const_reference back() const { return c.back(); }void push(const value_type &x) { c.push_back(x); }void pop() { c.pop_front(); }// ...
};

stack

在这里插入图片描述

template<class T, class Sequence=deque<T> >
class stack {
public:typedef typename Sequence::value_type value_type;typedef typename Sequence::size_type size_type;typedef typename Sequence::reference reference;typedef typename Sequence::const_reference const_reference;
protected:Sequence c;// 底层容器,默认是deque<T>
public:bool empty() const { return c.empty(); }size_type size() const { return c.size(); }reference top() { return c.back(); }const_reference top() const { return c.back(); }void push(const value_type &x) { c.push_back(x); }void pop() { c.pop_back(); }// ...
};

也可以指定其他容器,例如list、vector作为stack和queue的底层容器,因为它们内部也实现了对应所需要的方法。

queue<int, list<int>> q1;
for (long i = 0; i < 10; ++i) {q1.push(rand());
}stack<int, list<int>> s1;
for (long i = 0; i < 10; ++i) {s1.push(rand());
}stack<int, vector<int>> s2;
for (long i = 0; i < 10; ++i) {s2.push(rand());
}

stack 和 queue 都不允许遍历,也不提供迭代器
stack 和queue实际调用的是容器的函数,如果容器没有实现stack和queue的功能,比如map、set没有实现stack种的功能,不可以选择set或map作为stack queue的底层结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 脚本头(PyCharm+python头部信息、py头部信息、python头信息、py头信息、py文件头部)

文章目录 参考PyCharm设置脚本头头部信息 参考 https://developer.aliyun.com/article/1166544 https://blog.csdn.net/Dontla/article/details/131743495 https://blog.csdn.net/dongyouyuan/article/details/54408413 PyCharm设置脚本头 打开pycharm&#xff0c;点击file–…

【Harmony3.1/4.0】笔记六-对话框

概念 对话框在任何一款应用中&#xff0c;任何一个系统或者平台上使用都非常频繁&#xff0c;这里介绍一下鸿蒙系统中对话框的用法&#xff0c;分别为:普通文本对话框&#xff0c;自定义提示对话框&#xff0c;对话框菜单&#xff0c;警告提示对话框&#xff0c;列表选择对话框…

Unity 实现原神中的元素反应

一、元素反应 原神中共有七种元素&#xff0c;分别是水、火、冰、岩、风、雷、草。这七种元素能互相作用 Demo下载&#xff1a;Download 元素反应表格图示&#xff0c;可能不够精准 /火水雷冰草岩风绽放原激化火/蒸发超载融化燃烧结晶扩散烈绽放/水蒸发/感电冻结/碎冰绽放结晶…

Windows主机入侵检测与防御内核技术深入解析

第2章 模块防御的设计思想 2.1 执行与模块执行 本章内容为介绍模块执行防御。在此我将先介绍“执行”分类&#xff0c;以及“模块执行”在“执行”中的位置和重要性。 2.1.1 初次执行 恶意代码&#xff08;或者行为&#xff09;要在被攻击的机器上执行起来&#xff0c;看起…

Ubuntu 自己写的程序如何创建快捷方式

在Ubuntu中创建程序的快捷方式通常是通过将一个指向程序可执行文件的.desktop文件放入/usr/share/applications/或用户的~/.local/share/applications/目录来实现的。以下是创建快捷方式的基本步骤和示例&#xff1a; 在application里创建快捷方式 创建一个新的.desktop文件。…

【Linux】详解信号产生的方式

一、kill命令 在命令行中通过kill -数字 pid指令可以给指定进程发送指定信号。这里说明一下几个常见的信号&#xff1a; SIGINT&#xff08;2号信号&#xff09;&#xff1a;中断信号&#xff0c;通常由用户按下CtrlC产生&#xff0c;用于通知进程终止。SIGQUIT&#xff08;3号…

PG修改端口号与error: could not connect to server: could not connect to server 问题解决

刚开始学习PG修改端口号之后数据库端口号没变。 修改端口号&#xff1a;/usr/local/pgsql/data中的postgresql.conf中 修改后并不能直接生效需要重启PG&#xff1a; /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile restart重启后新…

c++在visual studio上的默认配置

右键 新建项 右键源文件 属性

企业OA管理|基于SprinBoot+vue的企业OA管理系统(源码+数据库+文档)

企业OA管理目录 基于SprinBootvue的企业OA管理系统 一、前言 二、系统设计 三、系统功能设计 1 管理员模块的实现 1.1 用户信息管理 1.2 公告信息管理 1.3 客户关系管理 1.4 通讯录管理 2 用户模块的实现 2.1 客户关系添加 2.2 通讯录添加 2.3 日程安排添加 四、…

3.Docker常用镜像命令和容器命令详解

文章目录 1、Docker镜像命令1.1 获取镜像1.2 查看镜像1.2.1、images命令列出镜像1.2.2、tag命令添加镜像标签1.2.3、inspect命令查看详细信息1.2.4、history命令查看镜像历史 1.3 搜索镜像1.4 删除和清理镜像1.4.1、使用标签删除镜像1.4.2、清理镜像 1.5 创建镜像1.5.1、基于已…

Nginx 从入门到实践(1)

Nginx 从入门到实践 Nginx Nginx 从入门到实践Nginx介绍Nginx常用功能1、Http代理&#xff0c;反向代理2、负载均衡3、动静分离4、Nginx配置文件结构 简述Nginx和Apache的差异编译安装nginx服务在线安装nginxnginx 状态统计nginx 访问控制(用户校验、客户端授权)用户校验基于客…

【vue,unapi】UniApp引入全局js实现全局方法,全局变量

创建一个全局文件utils.js export const baseUrl "https://www.baidu.com/"export const fn () > {console.log("demo"); } export const obj {baseUrl : "https://www.baidu.com/",demo(){console.log("demo2");} }第一种&#…

4月25日 C++day4

#include <iostream> using namespace std;class Person {const string name;int age;char sex; public:Person():name("lisi"){cout << "Person无参构造" << endl;}Person(string name,int age,char sex):name(name),age(age),sex(sex)…

最新windows版本erlang26.0和rabbitmq3.13下载

Erlang下载 官网下载&#xff1a;https://www.erlang.org/patches/otp-26.0 百度网盘&#xff1a;https://pan.baidu.com/s/1xU4syn14Bh7QR-skjm_hOg 提取码&#xff1a;az1t RabbtitMQ下载 官网下载&#xff1a;https://www.rabbitmq.com/docs/install-windows 百度网盘…

Python二进制文件转换为文本文件

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在日常编程中&#xff0c;我们经常会遇到需要将二进制文件转换为文本文件的情况。这可能是因…

Python请求示例电商商品详情数据(API接口开发系列),从入门到实战

在电商系统中&#xff0c;商品详情数据通常通过API接口提供。以下是一个从入门到实战的Python请求示例&#xff0c;展示如何获取电商商品详情数据。 入门篇&#xff1a;理解API接口 首先&#xff0c;你需要了解API&#xff08;应用程序接口&#xff09;的基本概念。API允许不…

Spring Boost + Elasticsearch 实现检索查询

需求&#xff1a;对“昵称”进行“全文检索查询”&#xff0c;对“账号”进行“精确查询”。 认识 Elasticsearch 1. ES 的倒排索引 正向索引 对 id 进行检索速度很快。对其他字段即使加了索引&#xff0c;只能满足精确查询。模糊查询时&#xff0c;逐条数据扫描&#xff0c…

VMware17Pro虚拟机安装macOS教程(超详细)

目录 1. 前言2. 下载所需文件3. 安装VMware3.1 安装3.2 启动并查看版本信息3.3 虚拟机默认位置配置 4. 安装补丁4.1 解压补丁4.2 结束VMware相关进程4.3 运行补丁包 5. 安装macOS5.1 新建虚拟机5.2 修改虚拟机配置5.3 安装操作系统5.3.1 选择 ISO 映像文件5.3.2 开启虚拟机5.2.…

重仓比特币

作者&#xff1a;Arthur Hayes Co-Founder of 100x. 编译&#xff1a;liam ccvalue (下文中表达的任何观点均为作者的个人观点&#xff0c;不应作为投资决策的依据&#xff0c;也不应被视为参与投资交易的建议或意见&#xff09;。 我们中断牛市常规节目&#xff0c;为您播报这…

SpringCloud 之 服务提供者

前提 便于理解,我修改了本地域名》这里!!! 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1 eureka7003.com学习Rest实例之提供者 提供者模块展示 1、导入依赖 <!-- 实体类 Web--><dependency><groupId>com.jyl</groupId><…