C++初阶:stack和queue使用及模拟实现

news2024/11/20 11:20:02

stack的介绍和使用

stack的介绍

堆栈 - C++ 参考 (cplusplus.com)

翻译 :
1. stack 是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
2. stack 是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部( 即栈顶 ) 被压入和弹出。
3. stack 的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty :判空操作
back :获取尾部元素操作
push_back :尾部插入元素操作
pop_back :尾部删除元素操作
4. 标准容器 vector deque list 均符合这些需求,默认情况下,如果没有为 stack 指定特定的底层容器,默认情况下使用deque

stack的使用

样例:

void test_stack1()
{
	//bit::stack<int, list<int>> st;
	//bit::stack<int, vector<int>> st;
	bit::stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);

	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;
}

 stack的模拟实现

#include<vector>
namespace bite
{
 template<class 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:
 std::vector<T> _c;
 };
}

queue的介绍和使用

queue的介绍

队列 - C++ 参考 (cplusplus.com)

翻译:
1. 队列是一种容器适配器,专门用于在 FIFO 上下文 ( 先进先出 ) 中操作,其中从容器一端插入元素,另一端提取元素。
2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类, queue 提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:
empty :检测队列是否为空
size :返回队列中有效元素的个数
front :返回队头元素的引用
back :返回队尾元素的引用
push_back :在队列尾部入队列
pop_front :在队列头部出队列
4. 标准容器类 deque list 满足了这些要求。默认情况下,如果没有为 queue 实例化指定容器类,则使用标准容器deque

queue的使用

 queue的模拟实现

因为 queue 的接口中存在头删和尾插,因此使用 vector 来封装效率太低,故可以借助 list 来模拟实现 queue ,具体如下:
#include <list>
namespace bite
{
 template<class 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:
 std::list<T> _c;
 };
}

容器适配器

什么是适配器

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

STL标准库中stackqueue的底层结构

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

 deque的简单介绍(了解)

deque的原理介绍

deque( 双端队列 ) :是一种双开口的 " 连续 " 空间的数据结构 ,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1) ,与 vector 比较,头插效率高,不需要搬移元素;与 list 比较,空间利用率比较高。
deque 并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际 deque 类似于一个动态的二维 数组 ,其底层结构如下图所示:
双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其 整体连续 以及随机访问的假象,落 在了 deque 的迭代器身上, 因此 deque 的迭代器设计就比较复杂,如下图所示:

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

 deque的缺陷

vector 比较 deque 的优势是:头部插入和删除时, 不需要搬移元素,效率特别高 ,而且在 扩容时,也不 需要搬移大量的元素 ,因此其效率是比 vector 高的。
list 比较 ,其底层是连续空间, 空间利用率比较高 ,不需要存储额外字段。
但是, deque 有一个致命缺陷:不适合遍历,因为在遍历时, deque 的迭代器要频繁的去检测其是否移动到 某段小空间的边界,导致效率低下 ,而序列式场景中,可能需要经常遍历,因此 在实际中,需要线性结构 时,大多数情况下优先考虑 vector list deque 的应用并不多,而 目前能看到的一个应用就是, STL 用其作 stack queue 的底层数据结构。
例子:
#include<iostream>
using namespace std;

#include<stack>
#include<deque>
#include<algorithm>

void test_op1()
{
	srand(time(0));
	const int N = 1000000;

	deque<int> dq;
	vector<int> v;

	for (int i = 0; i < N; ++i)
	{
		auto e = rand() + i;
		v.push_back(e);
		dq.push_back(e);
	}

	int begin1 = clock();
	sort(v.begin(), v.end());//排序涉及到遍历数组
	int end1 = clock();

	int begin2 = clock();
	sort(dq.begin(), dq.end());
	int end2 = clock();

	printf("vector:%d\n", end1 - begin1);
	printf("deque:%d\n", end2 - begin2);
}


结果:
vector:1810
deque:7265

为什么选择 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 不仅效率高,而且内存使用率高。
结合了 deque 的优点,而完美的避开了其缺陷。

总结:

STL标准库中对于stackqueue的模拟实现

 stack的模拟实现

#include<deque>
namespace bit
{
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;
 };
}

 queue的模拟实现

#include<deque>

namespace bit
{
 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;
 };
}

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

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

相关文章

【Java笔记】多线程0:JVM线程是用户态还是内核态?Java 线程与OS线程的联系

文章目录 JVM线程是用户态线程还是内核态线程什么是用户态线程与内核态线程绿色线程绿色线程的缺点 线程映射稍微回顾下线程映射模型JVM线程映射 线程状态操作系统的线程状态JVM的线程状态JVM线程与OS线程的状态关系 Reference 今天复盘一下Java中&#xff0c;JVM线程与实际操作…

大模型学习笔记一

前言 随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开启了学习机器学习&#xff0c;本文就介绍了机器学习的基础内容。 一、AI是什么&#xff1f; 二、大模型能干什么 大模型&#xff0c;全称「大语言模型」&#xff0c;英文「Large…

栈的应用——用栈实现算数混合运算表达式的计算

1、单目运算符双目运算符 算数运算符分为单目运算符和双目运算符等 单目运算符只需要一个操作数,双目运算符需要两个操作数 双目运算符最常见:常见的算术运算符:*/,比较运算符:<>=等等以下是一些单目运算符:正号 (+): 用于表示正数或给数值一个正号。例如:+5 仍然…

MySql 实战大数据查询-(表分区实现)

一 mysql分区&#xff1a; 分区是将单个表按照某种规则划分成多个子集&#xff0c;每个子集称为一个分区。常见的分区策略包括按照时间范围、范围值、列表等进行分区。 优点&#xff1a; 查询性能更好&#xff0c;涉及分区键的查询&#xff0c;数据库引擎可以只扫描特定分区&…

最优算法100例之30-表示数值的字符串

专栏主页&#xff1a;计算机专业基础知识总结&#xff08;适用于期末复习考研刷题求职面试&#xff09;系列文章https://blog.csdn.net/seeker1994/category_12585732.html 题目描述 请实现一个函数用来判断字符串是否表示数值&#xff08;包括整数和小数&#xff09;。例如&a…

卷积篇 | YOLOv8改进之引入全维度动态卷积ODConv | 即插即用

前言:Hello大家好,我是小哥谈。ODConv是一种关注了空域、输入通道、输出通道等维度上的动态性的卷积方法,一定程度上讲,ODConv可以视作CondConv的延续,将CondConv中一个维度上的动态特性进行了扩展,同时了考虑了空域、输入通道、输出通道等维度上的动态性,故称之为全维度…

LeetCode第六题:Z 字形变换 【6/1000 python】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 LeetCode解锁1000题: 打怪升级之旅htt…

springboot实战---7.springboot制作Docker镜像

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;SpringBoot &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&…

七、Promethus监控系统

一、普罗米修斯监控系统 1、为什么需要监控&#xff1a; ① 实时收集数据&#xff1a;监控工具能够实时收集关于系统、应用、网络等各方面的数据&#xff0c;包括性能指标、错误日志、用户行为等。 ② 及时发现问题&#xff1a;通过实时数据收集和分析&#xff0c;监控系统能…

带头双向循环链表,顺序表和链表的比较

双向链表 单链表结点中只有一个指向其后继的指针&#xff0c;使得单链表只能从前往后依次遍历&#xff0c;要访问某个结点的前驱&#xff08;插入、删除操作时&#xff09;&#xff0c;只能从头开始遍历&#xff0c;访问前驱的时间复杂度为O(N)。为了克服这个缺点&#xff0c;…

SSM实战项目——哈哈音乐(二)后台模块开发

1、项目准备 ① 引入后台模块&#xff08;hami-console&#xff09;需要的依赖 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0…

金融贷款批准预测项目

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 在金融服务行业&#xff0c;贷款审批是一项关键任务&#xff0c;它不仅关系到资金的安全&#xff0c;还直接影响到金融机构的运营效率和风险管理…

LIN总线基础

文章目录 1 什么是LIN 总线&#xff1f;1.1 LIN总线的历史 2.LIN总线的特点3. 应用4 LIN总线基本概念4.1 LIN报文帧结构4.1.1 主节点与从节点4.1.2 调度表4.1.3网络管理4.1.4 帧头结构4.1.4.1 电平 1 什么是LIN 总线&#xff1f; LIN(Local Interconnect Network)是一种低成本…

linux 搭建Samba服务

Samba简介 SAMBA是⼀个实现不同操作系统之间⽂件共享和打印机共享的⼀种SMB协议的免费软件&#xff0c; SMB(Server Message block)协议是window下所使⽤的⽂件共享协议&#xff0c;我们在linux系统或 者其类unix系统当中可以通过samba服务来实现SMB功能。 &#xff08;1&…

Linux离线安装python3(源码编译)

1、下载python包 下载python3.9.6的源码包 python下载 下载后&#xff0c;解压&#xff0c;目录如下&#xff1a; -rw-------. 1 root root 1454 Aug 26 2023 anaconda-ks.cfg -rw-r--r--. 1 root root 25640094 Apr 4 21:52 Python-3.9.6.tgz drwxrwxr…

LC 96.不同的二叉搜索树

96.不同的二叉搜索树 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a; n 3 输出&#xff1a; 5 示例 2&#xff1a; 输入&#xff1a;…

配置启动nacos,保姆级教程

下载nacos 下载链接 https://github.com/alibaba/nacos/releases进去下拉&#xff0c;找到下载版本信息。 下载后如图所示。 配置数据库 在我们的conf文件夹中有一个nacos-mysql的数据库文件 我们需要导入数据库&#xff0c;可通过工具Navicat等进行导入。 会有一下几张表…

【面试经典150 | 动态规划】交错字符串

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;动态规划 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行…

JAVA毕业设计133—基于Java+Springboot+Vue的网上宠物店商城管理系统(源代码+数据库+12000字论文)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的网上宠物店商城管理系统(源代码数据库12000字论文)133 一、系统介绍 本项目前后端分离&#xff0c;分为管理员、用户两种角色 1、用户&#xff1a; 注册…

聚合DNS管理系统v1.0全新发布 域名解析管理系统

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。本系统支持多用户&…