C++之stack 和 queue

目录

前言

1.stack的介绍和使用

1.1 stack的介绍

1.2 stack的使用

1.3 stack 的模拟

2. queue的介绍和使用

2.1 queue的介绍

 2.2 queue的使用

2.3 queue的模拟

3.适配器

3.1 什么是适配器

3.2 STL标准库中stack和queue的底层结构

3.3 deque 的介绍(了解)

3.3.1 deque的原理

3.3.2 deque 的缺陷

3.4 STL标准库中对于stack和queue的模拟实现

3.4.1 stack 的模拟

3.4.2 queue 的模拟

测试代码参考

结束语


前言

在数据结构部分我们通过C实现了栈和队列,本节我们将了解C++版本下的

stack和queue。我们将会很轻松的学习这部分知识。

1.stack的介绍和使用

1.1 stack的介绍

 后进先出

1.2 stack的使用

函数加接口说明 函数加接口说明
stack()    构造空的栈   empty()检测stack是否为空
size()返回stack中元素的个数  top()返回栈顶元素的引用
push()将元素val压入stack中   pop()将stack中尾部的元素弹出 

void test_stack() {stack<int>s1;s1.push(1);s1.push(2);s1.push(3);s1.push(4);s1.push(5);cout << s1.size() << endl;cout << s1.top() << endl;s1.pop();cout << s1.top() << endl;
}

1.3 stack 的模拟

stack我们是先进先出,并从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

我们将vector设为私有成员

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

这样子实现有个缺陷,如果我们需要实现一个链式栈就无法,可能会想到改成list,但是很麻烦。

我们可以导入一个容器类来进行实现。在后面的适配器我们会讲到。

2. queue的介绍和使用

2.1 queue的介绍

 

1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元 素,另一端提取元素。

2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供 一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。

3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。

该底层容器应至少 支持以下操作:

empty:检测队列是否为空    size:返回队列中有效元素的个数

front:返回队头元素的引用   back:返回队尾元素的引用

push_back:在队列尾部入队列    pop_front:在队列头部出队列

4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。 

 2.2 queue的使用

void test_queue() {queue<int>q1;q1.push(1);q1.push(2);q1.push(3);q1.push(4);q1.push(5);cout << q1.size() << endl;cout << q1.front() << endl;cout << q1.back() << endl;q1.pop();cout << q1.front() << endl;}

2.3 queue的模拟

因为queue的接口中存在头删和尾插,因此使用vector来封装效率太低,故可以借助list来模拟实 现queue。

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

通过官方的queue和stack我们可以看到,在类模版中都定义了一个class Container=deque<T>;

所以我们同样类似这样子写,在后续我们会讲解deque的知识。

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

这样我们既可以写顺序栈也可以链式栈

my_stack::stack<int,vector<int>>s1;

my_stack::stack<int,list<int>>s1;

这里我们使用了vector来当默认参数,而在方法中却穿插了链表的方法,编译时却没有报错,这是因为这是类模版,在主函数类模板实例化时,按需实例化,使用哪些成员函数就实例化哪些,不会全实例化,所以当我们使用vector的时候,不调用list的方法就行了

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

3.适配器

3.1 什么是适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设 计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

3.2 STL标准库中stack和queue的底层结构

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

3.3 deque 的介绍(了解)

3.3.1 deque的原理

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端 进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与 list比较,空间利用率比较高。

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个 动态的二维数组,其底层结构如下图所示:

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问 的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示: 

那deque是如何借助其迭代器维护其假想连续的结构呢? 如下图所示

3.3.2 deque 的缺陷

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩 容时,也不需要搬移大量的元素,因此其效率是必vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

但是,deque不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其 是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实 际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,

而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构 

为什么选择deque作为stack和queue的底层默认容器 

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性 结构,都可以作为stack的底层容器,比如vector和list都可以;

queue是先进先出的特殊线性数据 结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如 list。

但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进 行操作。

2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的 元素增长时,deque不仅效率高,而且内存使用率高。

3.4 STL标准库中对于stack和queue的模拟实现

3.4.1 stack 的模拟

#include<deque>
namespace my_stack
{template<class T, class Con = deque<T>>//template<class T, class Con = vector<T>>//template<class T, class Con = list<T>>class stack{public:stack() {}void push(const T& x){ _c.push_back(x); }void pop() { _c.pop_back(); }T& top() { return _c.back(); }const T& top()const { return _c.back(); }size_t size()const { return _c.size(); }bool empty()const { return _c.empty(); }private:Con _c;};
}

3.4.2 queue 的模拟

#include<deque>
#include <list>
namespace my_queue
{template<class T, class Con = deque<T>>//template<class T, class Con = list<T>>class queue{public:queue() {}void push(const T& x) {_c.push_back(x); }void pop() {_c.pop_front(); }T& back() { return _c.back(); }const T& back()const { return _c.back(); }T& front() { return _c.front(); }const T& front()const { return _c.front(); }size_t size()const { return _c.size(); }bool empty()const { return _c.empty(); }private:Con _c;};
}

测试代码参考

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
#include "stack.h"
#include "queue.h"
void print() {}
void test_stack() {stack<int>s1;s1.push(1);s1.push(2);s1.push(3);s1.push(4);s1.push(5);cout << s1.size() << endl;cout << s1.top() << endl;s1.pop();cout << s1.top() << endl;
}
void test_queue() {queue<int>q1;q1.push(1);q1.push(2);q1.push(3);q1.push(4);q1.push(5);cout << q1.size() << endl;cout << q1.front() << endl;cout << q1.back() << endl;q1.pop();cout << q1.front() << endl;}
int main() {//test_stack();//test_queue();/*my_stack::stack<int,list<int>>s1;s1.push(1);s1.push(2);s1.push(3);s1.push(4);s1.push(5);cout << s1.size() << endl;cout << s1.top() << endl;s1.pop();cout << s1.top() << endl;cout << s1.back() << endl;cout << s1.front() << endl;*/my_queue::queue<int> q1;q1.push(1);q1.push(2);q1.push(3);q1.push(520);q1.push(1314);cout << q1.back() << endl;cout << q1.front() << endl;q1.pop();cout << q1.back() << endl;cout << q1.front() << endl;my_stack::stack<int> q2;q2.push(1);q2.push(2);q2.push(3);q2.push(520);q2.push(1314);cout << q2.top() << endl;cout << q2.top()<< endl;q2.pop();cout << q2.top() << endl;const my_stack::stack<int>& crefMyStack = q2;cout << "Top element (const) is: " << crefMyStack.top() << endl;return 0;
}

结束语

本次博客内容就到此结束了。理所当然C++下的stack和queue的实现更加的简便和多种多样!

最后感谢各位友友们的捧场和支持,给小编留个赞吧!!!

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

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

相关文章

智慧城市主要运营模式分析

(一)运营模式演变 作为新一代信息化技术落地应用的新事物,智慧城市在建设模式方面借鉴了大量工程建设的经验,如平行发包(DBB,Design-Bid-Build)、EPC工程总承包、PPP等模式等,这些模式在不同的发展阶段和条件下发挥了重要作用。 在智慧城市发展模式从政府主导、以建为主、…

一日连发两款视频大模型,火山引擎杀疯了!

9月24日&#xff0c;字节跳动旗下火山引擎在深圳举办AI创新巡展&#xff0c;并首次对外发布豆包视频生成-PixelDance、豆包视频生成-Seaweed两款AI大模型&#xff0c;并公布了多项AI大模型的全新升级&#xff0c;以一种全新的姿态迎接AI时代的到来。 雷科技此次受邀参与巡展&a…

David律所代理Jose Martin幽默水果版权首发维权,尚未TRO

案件基本情况&#xff1a;起诉时间&#xff1a;2024/9/18案件号&#xff1a;2024-cv-08484原告&#xff1a;Jose Martin原告律所&#xff1a;David起诉地&#xff1a;伊利诺伊州北部法院涉案商标/版权&#xff1a;原告品牌简介&#xff1a;西班牙的卓越艺术家Jose Martin以他非…

深度学习:常见损失函数简介--名称、作用和用法

目录 1. L1 Loss 2. NLL Loss (Negative Log Likelihood Loss) 3. NLLLoss2d 4. Gaussian NLL Loss 5. MSE Loss (Mean Squared Error Loss) 6. BCE Loss (Binary Cross-Entropy Loss) 7. Smooth L1 Loss 8. Cross Entropy Loss 1. L1 Loss 作用&#xff1a;计算预测值…

数据结构(Day18)

一、周学习内容 1、9.18 数据结构&#xff08;Day15&#xff09;-CSDN博客 2、9.19 数据结构&#xff08;Day16&#xff09;-CSDN博客 3、9.20 链表 目的 插入删除不需要移动任何节点&#xff08;元素&#xff09;。 不需要预估存储空间大小&#xff0c;长度动态增长或减小。…

jQuery——jQuery的2把利器

1、jQuery 核心函数 ① 简称&#xff1a;jQuery 函数&#xff0c;即为 $ 或者 jQuery ② jQuery 库向外直接暴露的是 $ 或者 jQuery ③ 引入 jQuery 库后&#xff0c;直接使用 $ 即可 当函数用&#xff1a;$&#xff08;xxx&#xff09; 当对象用&#xff1a;$.xxx&#x…

类与对象—python

一、类的含义 1.1类的作用&#xff08;理解&#xff09; 收集学生信息时&#xff0c;如果让同学们自主填写&#xff0c;信息的顺序、格式不一&#xff0c;内容混乱。如果发给同学们既定的表格&#xff0c;同学们按照规定的顺序、格式进行填写&#xff0c;那信息就会一目了然&…

深度学习03-神经网络01-什么是神经网络?

神经网络的基本概念 人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;&#xff1a; 是一种模仿生物神经网络的计算模型。由多个神经元&#xff08;或称为节点&#xff09;组成&#xff0c;这些节点通过不同的连接来传递信息。 每个神经元可以接…

Git从了解到操作

Git常用命令 基本的linux命令 ls / ll 查看当前目录( ls 是查看目录有哪些文件夹&#xff0c;ll 是查看隐藏文件)cat 查看文件内容touch 创建文件vi vi编辑器 (使用 vi 编辑器是为了方便展示效果&#xff0c;也可以记事本、editPlus、notPad等其它编辑器) 备注 Git GUl: Gi…

html TAB、table生成

1. 代码 <!DOCTYPE html> <head> <meta charset"UTF-8"> <title>Dynamic Tabs with Table Data</title> <style> /* 简单的样式 */ .tab-content { display: none; border: 10px solid #ccc; padding: 30px; mar…

全志A133 android10 适配EC20 4G模块

一&#xff0c;移植适配 1. 驱动移植 代码路径&#xff1a;longan/kernel/linux-4.9/drivers/usb/serial/option.c diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9f96dd2..2f25466 100644 --- a/drivers/usb/serial/option.cb/drivers/us…

单例模式(饿汉式-懒汉式)

我给面试官讲解了单例模式后&#xff0c;他对我竖起了大拇指&#xff01;https://blog.csdn.net/weixin_41949328/article/details/107296517?ops_request_misc%257B%2522request%255Fid%2522%253A%2522FAEE9ABD-432D-416C-98C6-9DD939138DEB%2522%252C%2522scm%2522%253A%252…

Spring AOP实现原理-动态代理

目录 代理的基础概念 示例1&#xff1a;静态代理&#xff08;场景&#xff1a;客户通过中介租房东的房子&#xff09; 示例2&#xff1a;JDK动态代理实现房东、中介出租房屋 示例3&#xff1a;CGLib动态代理实现房东出租房屋 示例4&#xff1a;观察Spring IOC容器中代理对象…

【算法】贪心+堆排序实现大根堆及标准库容器类的融合使用

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

git push错误:Out of memory, malloc failed (tried toallocate 947912704 bytes)

目录 一、错误截图 二、解决办法 一、错误截图 因项目文件过大&#xff0c;http.postBuffer设置的内存不够&#xff0c;所以报错。 二、解决办法 打开cmd窗口&#xff0c;执行如下命令即可 git config --global http.postBuffer 1024000000 如图所示 执行完成以后&#…

NCNN 源码(1)-模型加载-数据预处理-模型推理

参考 ncnn 第一个版本的代码。 0 整体流程 demo&#xff1a;squeezenet ncnn 自带的一个经典 demo&#xff1a;squeezenet 的代码: // 网络加载 ncnn::Net squeezenet; squeezenet.load_param("squeezenet_v1.1.param"); squeezenet.load_model("squeezenet_…

RIFormer:保持你的视觉主干有效但移除令牌混合器

摘要 https://arxiv.org/pdf/2304.05659 本文研究了如何在去除其基本构建块中的标记混合器&#xff08;token mixers&#xff09;的同时保持视觉主干的有效性。标记混合器作为视觉变换器&#xff08;Vision Transformers, ViTs&#xff09;的自注意力机制&#xff0c;旨在实现…

【排序算法】选择排序、堆排序

文章目录 选择排序选择排序的概念选择排序的基本步骤&#xff1a;选择排序的特点选择排序的代码实现&#xff08;C语言&#xff09; 选择排序-优化双向选择排序的步骤 堆堆的基本概念堆排序详细步骤堆排序代码讲解 选择排序 选择排序的概念 选择排序是一种简单直观的排序算法。…

SpringBoot项目编译运行成功,但有些包名类名仍然下划线标红的解决方法 | Idea

目录 问题解决方案&#xff1a;方法一&#xff1a;方法二【我用这个成功的】 问题 如图&#xff0c;成功运行但有些包名类名仍然下划线标红&#xff0c;强迫症抓狂 成功运行&#xff1a; 有些包导入标红&#xff1a; 解决方案&#xff1a; 方法一&#xff1a; 点击fil…

分布式框架 - ZooKeeper

一、什么是微服务架构 1、单体架构 顾名思义一个软件系统只部署在一台服务器上。 ​ 在高并发场景中&#xff0c;比如电商项目&#xff0c;单台服务器往往难以支撑短时间内的大量请求&#xff0c;聪明的架构师想出了一个办法提高并发量&#xff1a;一台服务器不够就加一台&am…