【C++修炼之路】12. stack queue类

news/2024/11/7 18:41:24/

在这里插入图片描述
每一个不曾起舞的日子都是对生命的辜负

stack&&queue

  • 一. stack的介绍和使用
    • 1. stack的介绍
    • 2. stack的使用
  • 二. stack的模拟实现
  • 三. queue的介绍和使用
    • 1. queue的介绍
    • 2. queue的使用
  • 四. queue的模拟实现
  • 五. deque的介绍和使用
    • 1. deque的介绍
    • 2. deque的使用
    • 3. deque的缺陷

一. stack的介绍和使用

1. stack的介绍

stack的文档介绍

  1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。

  2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

  3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:

    • empty:判空操作
    • back:获取尾部元素操作
    • push_back:尾部插入元素操作
    • pop_back:尾部删除元素操作
  4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

    image-20230103161257627

2. stack的使用

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

二. stack的模拟实现

在开始之前,我们需要知道什么是设计模式:设计模式概念 目前有23种。

我们现在接触的模式有两种:适配器模式、迭代器模式

对于迭代器模式,使我们所熟知的,因为对于vector和list的模拟实现,都涉及到迭代器模式,迭代器模式将内部复杂的数据结构进行了封装,从而在上层使用中更为便捷,即不暴露底层细节,封装后提供统一的方式访问容器;而对于适配器模式:现实生活中,被称为适配器的有电源等待,因此适配器本质是已有的东西,封装转换出你想要的东西。

对于stack的模拟实现,下面将用适配器转换,vector、list

stack.h

#pragma once
#include<vector>
#include<list>//stack的模拟实现
namespace cfy
{template<class T, class Container = vector<T>>//适配器:调用一种结构实现另一种class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}const T& top(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include"Stack.h"int main()
{cfy::stack<int, vector<int>> st;st.push(1);st.push(2);st.push(3);st.push(4);while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;return 0;
}

image-20230103163628742

当然,也可以用list替换vector,同时里面的函数也要改成list类的。

三. queue的介绍和使用

1. queue的介绍

queue的文档介绍

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

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

  3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

    • empty:检测队列是否为空
    • size:返回队列中有效元素的个数
    • front:返回队头元素的引用
    • back:返回队尾元素的引用
    • push_back:在队列尾部入队列
    • pop_front:在队列头部出队列
  4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

image-20230103164214422

2. queue的使用

函数声明接口说明
queue()构造空的队列
empty()检测队列是否为空,是返回true,否则返回false
size()返回队列中有效元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列

四. queue的模拟实现

同stack,模拟实现也是采用适配器的方式,因为stack和queue都不存在迭代器。由于queue经常头删,用vector代价高,因此这里使用list的适配器。

queue.h

#pragma once
#include<vector>
#include<list>
//queue的模拟实现
namespace cfy
{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(){return _con.front();}const T& back(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include"queue.h"int main()
{cfy::queue<int, list<int>> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;return 0;
}

image-20230103165506697

当然,用vector也是可以的,同时需要将对应的函数改成vector类的。

五. deque的介绍和使用

1. deque的介绍

image-20230103172025844

image-20230103172055127

我们查文档发现,虽然stack用了适配器模式,但是其适配器并不是vector,而是deque作为缺省值,这也正对应了stack介绍的第四条,如果不传指定的适配器,stack就采用dequeimage-20230103165847132

那么deque是什么呢?——双端队列

deque的文档介绍

我们在C++上一篇list的结尾叙述了vector、list的优缺点:vector的头部中部插入效率低以及扩容消耗,list不支持随机访问,CPU高速缓存命中率低,而deque恰恰会与其互补。即deque双端队列兼具vector、list的优点,可以支持下标访问,头部尾部效率高。

2. deque的使用

deque支持头插尾插,头删尾删,下面就直接使用deque:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<deque>
using namespace std;int main()
{deque<int> d;d.push_back(1);//支持尾插d.push_back(2);d.push_back(3);d.push_back(4);d.push_front(10);//支持头插d.push_front(20);for (size_t i = 0; i < d.size(); i++)//支持下标随机访问{cout << d[i] << " ";}cout << endl;return 0;
}

image-20230103171301152

3. deque的缺陷

deque并没有想象的那么好,否则vector和list也不会存在,deque的使用效率不高,因为效率不如指定场景的vector和list。这一点可以用排序测试。

对于deque的原理,在STL源码剖析的143页:STL源码剖析电子版


http://www.ppmy.cn/news/9086.html

相关文章

【Node】Node.js安装与配置(详细步骤)

Node.js安装与配置&#xff08;详细步骤&#xff09;一、安装Node.js1.1 下载1.2 安装1.3 环境变量二、验证是否安装成功三、修改模块下载位置3.1 查看npm默认存放位置3.2 在 nodejs 安装目录下&#xff0c;创建 “node_global” 和 “node_cache” 两个文件夹3.3 修改默认文件…

MySQL调优-Explain详解和索引最佳实践

目录 MySQL调优-Explain详解和索引最佳实践 Explain工具介绍 Explain分析示例 explain 两个变种 explain中的列 1.id列 2.select_type列 3. table列 4.type列 5. possible_keys列 6. key列 7. key_len列 8. ref列 9. rows列 10.Extra列 索引最佳实践 1.全值匹配 …

Maven安装及配置

1.下载 Maven – Download Apache Maven 2.安装 maven压缩包解压到一个没有中文&#xff0c;空格或其他特殊字符的文件夹内即可使用。 3.配置环境变量 1.右键此电脑->属性->高级系统设置->环境变量 2.新建系统变量MAVEN_HOME 3.编辑系统变量Path&#xff0c;添…

设计模式第3式:策略模式

前言 策略模式定义了算法族&#xff0c;分别封装起来&#xff0c;让它们之间可以相互替换&#xff0c;此模式让算法的变化独立于使用算法的客户。 正文 《head first设计模式》给的例子很好&#xff0c;它通过改造了一个Duck功能&#xff0c;将“行为”抽象成接口&#xff0…

【韩顺平Linux】学习笔记3

【韩顺平Linux】学习笔记3一、文件目录指令pwd指令 ls指令cd指令mkdir指令rmdir指令touch指令cp指令rm指令mv指令cat指令more指令less 指令echo指令 head指令tail指令> 指令 >>指令ln指令history指令二、时间日期指令三、查找指令四、压缩和解压一、文件目录指令 根目…

电子游戏销售之回归模型与数据可视化

电子游戏销售之回归模型与数据可视化 文章目录电子游戏销售之回归模型与数据可视化0、写在前面1、回归模型1.1 模型建立准备1.2 建立模型1.3 模型分析2、数据可视化3、参考资料0、写在前面 该篇文章的任务包括以下3个方面 检测与处理缺失值建立回归模型数据可视化 实验环境 Pyt…

【数据结构】LeetCode移除链表元素、反转链表、链表的中间结点

目录 一、移除链表元素 1、题目说明 2、题目解析 二、反转链表 1、题目说明 2、题目解析 三、链表的中间结点 1、题目说明 2、题目解析 一、移除链表元素 1、题目说明 题目链接&#xff1a;移除链表的元素 给你一个链表的头节点 head &#xff0c;和一个整数 val&#xff0c;…

DALLE2-文本图像生成

文章目录摘要算法解码器prior图像处理变体插值文本差异限制论文&#xff1a; 《Hierarchical Text-Conditional Image Generation with CLIP Latents》github&#xff1a; https://github.com/lucidrains/DALLE2-pytorchhttps://github.com/LAION-AI/dalle2-laion摘要 CLIP已经…