STL stack,queue,deque以及适配器

目录

  • stack
    • stack的使用
    • stack模拟实现
  • queue
    • queue的使用
    • queue模拟实现
  • 适配器
  • deque

stack

stack的使用

下面是stack库中的接口函数,有了前面的基础,我们可以根据函数名得知函数的作用

函数说明
stack()构造空栈
empty()判断栈是否为空
size()返回栈中元素个数
top返回栈顶元素
push()将值从栈顶压入栈内
pop()在栈顶出栈

stack模拟实现

栈其实就是一种特殊的vector,因此可以使用vector模拟实现stack
比较容易:

#include <iostream>
#include <vector>
using namespace std;namespace my_stack
{template<class T>class stack{public:void push(const T& val){_v.push_back(val);}void pop(){_v.pop_back();}T& top(){return _v.back();}bool empty(){return _v.empty();}size_t size(){return _v.size();}private:vector<T> _v;};
}

queue

queue的使用

函数说明
queue()构造空队列
empty()判断队列是否为空
size()返回队列中元素个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾入队
pop()在队头出队

queue模拟实现

queue的接口中存在头删,用vector实现起来效率太低,所以可以使用list实现

#include <iostream>
#include <list>
using namespace std;namespace my_queue
{template<class T>class queue{public:void push(const T& val){_lt.push_back(val);}void pop(){_lt.pop_front();}T& front(){return _lt.front();}T& back(){return _lt.back();}bool empty(){return _lt.empty();}size_t size(){return _lt.size();}private:list<T> _lt;};
}

适配器

适配器是一种设计模式,该模式是将一个类的接口转换成客户希望的另一个接口
对已有的东西,进行适配转换

在C语言中,我们习惯用顺序表去实现栈,因为使用顺序表实现栈比较方便
但是也可以用链表去实现,我们如果想去用链表实现栈,还需要再写一套,会比较麻烦

在C++中,有了适配器,不用再实现两遍了
我们可以使用适配器进行实现,这样我们就可以做到数组栈和链表栈秒切换了
在用适配器实现后,平时使用时感觉不到差异,但是两者的底层逻辑完全不同

下面我们用适配器设计出stack

首先我们添加一个模板参数
template<class T,class Container>Container就是适配器
在实例化的时候,我们需要指定适配器是哪一种容器

接下来,把成员变量改为适配器

	template<class T,class Container>class stack{public:private:Container _con;};

接下来,我们按照前面模拟实现的stack把所有_v改为_con就可以了

namespace my_stack
{template<class T,class Container>class stack{public:void push(const T& val){_con.push_back(val);}void pop(){_con.pop_back();}T& top(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}

接下来我们看一下 用适配器实现的数组栈和链表栈

int main()
{my_stack::stack<int, vector<int>> st;st.push(1);st.push(2);st.push(3);st.push(4);st.push(5);st.push(6);while (!st.empty()){cout << st.top() << " ";st.pop();}//输出 6 5 4 3 2 1cout << endl;my_stack::stack<int, list<int>> st1;st1.push(1);st1.push(2);st1.push(3);st1.push(4);st1.push(5);st1.push(6);while (!st1.empty()){cout << st1.top() << " ";st1.pop();}//输出 6 5 4 3 2 1cout << endl;
}

下面我们也可以使用适配器实现queue

namespace my_queue
{template<class T, class Container>class queue{public:void push(const T& val){_con.push_back(val);}void pop(){_con.pop_front();}T& front(){return _con.front();}T& back(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}

这里的适配器类型只能是list,不能是vector因为vector中不支持pop_front头删,无法支持queuepop

虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配
,这是因为stack和队列只是对其他容器的接口进行了包装


deque

我们看STL中,stackqueue的实现
可以发现它们的适配器默认为deque<T>
在这里插入图片描述

在这里插入图片描述
这个deque是什么容器,我们下面来看一看

deque叫双端队列(但不是队列),是一种双开口的“连续空间”的数据结构
在这里插入图片描述
deque可以在头尾两端进行插入和删除操作,时间复杂度为O(1),效率高,并且支持[]



deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维
数组

deque中有一段中控数组(本质是指针数组),其中每一个元素指针都指向一个固定大小的缓冲区
在这里插入图片描述
插入元素先从存入中控数组中间位置指针指向的缓冲区,因为要保证头插和尾插都有空间
如果一个Buff满了,就在其下一个指针指向的Buff中存储数据
如果中控数组满了,扩容即可,对于指针类型的拷贝消耗少

deque相比于vector
极大缓解了扩容的问题,同时解决了头删和头插带来的效率低的问题
但是deque的[]随机访问相对于vector的随机访问还是有差距的,因为要计算随机访问的位置在哪个Buff的哪个位置上

假设要访问位置i上的元素
1.先看i在不在第一个Buff中,如果在就直接找到位置访问
2.如果不在第一个Buff,i-=第一个Buffsize()
在第i/buffsizeBuff
在这个Buffi%buffsize位置上
而vector中的[]就是直接解引用指针,效率高

deque相比于list:
deque支持随机访问
cpu高速访问效率搞
但是deque中间位置元素的插入和删除效率没有list

所以deque的最大价值就在于它的头插,头删,尾插,尾删的效率高
这也正是stackqueue中适配器最需要的特点,所以deque作为stackqueue的默认适配器最合适

用deque为默认适配器实现stackqueue

#include <deque>
#include <stack>
#include <list>
#include <iostream>
using namespace std;
namespace my_queue
{template<class T, class Container = deque<T>>class queue{public:void push(const T& val){_con.push_back(val);}void pop(){_con.pop_front();}T& front(){return _con.front();}T& back(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}namespace my_stack
{template<class T, class Container = deque<T>>class stack{public:void push(const T& val){_con.push_back(val);}void pop(){_con.pop_back();}T& top(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}

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

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

相关文章

1992-2022年全国31省市产业升级、产业结构高级化水平面板数据(含原始数据和计算过程)

1992-2022年全国31省市产业升级、产业结构高级化水平面板数据&#xff08;含原始数据和计算过程&#xff09; 1、时间&#xff1a;1992-2022年 2、指标&#xff1a;地区生产总值、第一产业增加值、第二产业增加值、第三产业增加值、第一产业占GDP比重、第二产业占GDP比重、第…

【分享】PDF如何拆分成2个或多个文件呢?

当我们需要把一个多页的PDF文件拆分成2个或多个独立的PDF文件&#xff0c;可以怎么操作呢&#xff1f;这种情况需要使用相关工具&#xff0c;下面小编就来分享两个常用的工具。 1. PDF编辑器 PDF编辑器不仅可以用来编辑PDF文件&#xff0c;还具备多种功能&#xff0c;拆分PDF文…

哪吒汽车“三头六臂”之「浩智电驱」

撰文 / 翟悦 编审 / 吴晰 8月21日&#xff0c;在哪吒汽车科技日上&#xff0c;哪吒汽车发布“浩智战略2025”以及浩智技术品牌2.0。根据公开信息&#xff0c;主编梳理了以下几点&#xff1a;◎浩智滑板底盘支持400V/800V双平台◎浩智电驱包括180kW 400V电驱系统和250kW 800…

基于Spring Boot的住院病人管理系统设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的住院病人管理系统设计与实现&#xff08;Javaspring bootMySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java spring…

Python钢筋混凝土结构计算.pdf-混凝土强度设计值

计算原理&#xff1a; 需要注意的是&#xff0c;根据不同的规范和设计要求&#xff0c;上述公式可能会有所差异。因此&#xff0c;在进行混凝土强度设计值的计算时&#xff0c;请参考相应的规范和设计手册&#xff0c;以确保计算结果的准确性和合规性。 代码实现&#xff1a; …

Vue3列表竖向滚动(包含使用swiper的翻页效果)

一、使用element-plus表格进行滚动&#xff1a; 可以满足的需求&#xff1a;表格一行一行竖向滚动&#xff0c;类似走马灯。 不能满足的需求&#xff1a;表格分页竖向滚动&#xff0c;有翻页的效果。 代码&#xff1a; <template><el-table:data"tableData"…

在Nodejs中使用JWT进行鉴权

什么是 JSON Web Token&#xff08;JWT&#xff09;&#xff1f; JSON Web Token&#xff08;JWT&#xff09;是一种用于在web上传递信息的标准&#xff0c;它以JSON格式表示信息&#xff0c;通常用于身份验证和授权。 JWT由三个部分组成&#xff1a;Header&#xff08;头部&…

小白学Go基础01-Go 语言的介绍

Go 语言对传统的面向对象开发进行了重新思考&#xff0c;并且提供了更高效的复用代码的手段。Go 语言还让用户能更高效地利用昂贵服务器上的所有核心&#xff0c;而且它编译大型项目的速度也很快。 用 Go 解决现代编程难题 Go 语言开发团队花了很长时间来解决当今软件开发人员…

是否在业务中使用大语言模型?

ChatGPT取得了巨大的成功&#xff0c;在短短一个月内就获得了1亿用户&#xff0c;并激发了企业和专业人士对如何在他们的组织中利用这一工具的兴趣和好奇心。 但LLM究竟是什么&#xff0c;它们如何使你的企业受益?它只是一种炒作&#xff0c;还是会长期存在? 在这篇文章中我…

Redis 复制(replica)

1. 是什么 1.1 官网地址 https://redis.io/docs/management/replication/ 1.2 一句话 1. 就是主从复制&#xff0c;master以写为主&#xff0c;slave以读为主 2. 当master数据变化的时候&#xff0c;自动将新的数据异步同步到其它slave数据库 2. 能干嘛 1. 读写分离 2. 容灾…

Ubuntu系统下配置 Qt Creator 输入中文、配置软件源的服务器地址、修改Ubuntu系统时间

上篇介绍了Ubuntu系统下搭建QtCreator开发环境。我们可以发现安装好的QtCreator不能输入中文&#xff0c;也没有中文输入法供选择&#xff0c;这里需要进行设置。 文章目录 1. 配置软件源的服务器地址2. 先配置Ubuntu系统语言&#xff0c;设置为中文3. 安装Fcitx插件&#xff…

学习笔记-ThreadLocal

ThreadLocal 什么是ThreadLocal&#xff1f; ThreadLocal 是线程本地变量类&#xff0c;在多线程并行执行过程中&#xff0c;将变量存储在ThreadLocal中&#xff0c;每个线程中都有独立的变量&#xff0c;因此不会出现线程安全问题。 应用举例 解决线程安全问题&#xff1a;例…