【c++】stack和queue模拟实现

> 作者简介:დ旧言~,目前大二,现在学习Java,c,c++,Python等
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:能手撕stack和queue模拟

> 毒鸡汤:过错是暂时的遗憾,而错过则是永远的遗憾!

> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

🌟前言

        手撕stack和queue对比在数据结构中的模拟要比较简单,为什么呢?因为我们学习了参数模板这块,我们可以调用,所以模拟起来比较简单,具体是如何简单法呢,我们进入正文:

⭐主体

这里我们创建三个文件:stack.h,queue.h,test.cpp。


第一个:迭代器模式
迭代器模式就是在不暴露底层的细节的前提下,通过封装给用户提供统一的接口让用户访问容器里面的数据,我们使用的每个容器都可以通过创建迭代器变量的方式来访问容器里面的内容,并且访问的方式都是一样的,(*迭代器变量)可以得到并修改指定位置的数据,(迭代器++)可以让迭代器变量指向容器的下一个元素,通过上面的两个操作,不管是vector容器还是string容器还是后面要学的更加复杂的容器,我们都可以很简单的访问容器里面的内容,但是这些迭代器底层实现的原理是一样的吗?vector和string迭代器是通过创建一个指针变量来实现的,而list迭代器是创建一个类,通过这个类对list的数据进行封装来实现的,不同的容器的迭代器实现的方法也各不相同,但是作为使用者来说我们根本就不用了解这些迭代器的底层实现我们会用就行,并且迭代器的出现很大程度上降低了我们学习的成本,并且迭代器的出现还有助于维护数据的安全,如果我们认为的操作容器里面的数据的话,搞不好就将哪个重要的数据删除了,将另外一个地方的数据覆盖了,所以迭代器模式就对容器里面的数据进行了一下封装,我们要访问这些数据就只能通过迭代器的方式来进行访问,这样即降低了学习成本又保护了数据的安全,我们把这样的设计模式成为迭代器模式。
第二个:适配器模式
在之前的学习中我们知道stack对数据管理的方式是先入栈的数据后出栈,后入栈的数据先出栈,我们还知道queue对数据管理的方式是:先入队列的数据先出队列,后入队列的数据后出队列,这是两个容器对数据处理的方式,虽然这种处理数据的方式属于这些容器的,但是其他的容器也可以实现这样的功能,比如说vector和list都可以在容器的头部或者尾部插入或删除数据,如果我们只让vector或者list在容器的头部尾部插入删除数据的话,那是不是就相当于是stack了呢?如果我们只让vector或者list在头部删除数据在尾部插入数据的话,那这是不是就相当于queue了呢?所以在实现一个容器或者功能的时候,我们可以用现有东西进行一些简单的修改或者封装从而实现你想要的东西,那么这就是适配器模式:用已有的东西通过封装转换出来你想要的东西,那么我们这里的stack和queue就可以通过适配器模式来实现。

🌙stack模拟实现

       模拟实现C++的栈时,应该要考虑用什么作为它的底层,目前来看,貌似动态数组vector是个不错的选择,因为栈只需要在栈顶插入和删除元素。

        第二个模板参数的默认值给成vector<T>,这样就不需要用户自己传递第二个参数了。实现stack中的函数也很容易,只需要在函数内部调用vector的函数即可。

框架如下:

#include<iostream>
#include<vector>
#include<list>using namespace std;
namespace lyk
{template<class T, class continer = vector<int>>class stack{public:private:continer con;};
}

💫元素入栈

首先来实现一下stack的push函数因为stack在插入数据的时候只能在尾部插入数据,所以在stack的push函数里面就可以直接调用容器con的push_back函数来尾插数据,那么该函数的实现如下:

// 元素入栈
void push(const T& val)
{con.push_back(val);
}

💫元素出栈

stack中删除数据也只能删除尾部数组,所以实现pop函数的时候就可以直接调用容器con的pop_back函数来删除数据,那这里的代码就如下:

// 元素出栈
void pop()
{con.pop_back();
}

💫获取元素有效个数

复用vector类的函数即可获得有效元素的个数,代码如下:

// 返回栈中元素个数
size_t size()
{return con.size();
}

💫判断栈是否为空

复用vector类的判空函数,代码如下:

// 判断栈是否为空
bool empty()
{return con.empty();
}

💫返回栈顶元素

代码如下:

// 返回栈顶元素
const T& top()
{return con.back();
}

💫stack整体代码

#include<iostream>
#include<vector>
#include<list>using namespace std;
namespace lyk
{template<class T, class continer = vector<int>>class stack{public:// 元素入栈void push(const T& val){con.push_back(val);}// 元素出栈void pop(){con.pop_back();}// 返回栈中元素个数size_t size(){return con.size();}// 判断栈是否为空bool empty(){return con.empty();}// 返回栈顶元素const T& top(){return con.back();}private:continer con;};// 测试void test_stack(){lyk::stack<int> s1;s1.push(1);s1.push(2);s1.push(3);s1.push(4);while (!s1.empty()){cout << s1.top() << " ";s1.pop();}cout << endl;lyk::stack<int, list<int>> s2;s2.push(4);s2.push(3);s2.push(2);s2.push(1);while (!s2.empty()){cout << s2.top() << " ";s2.pop();}}
}

运行结果:

🌙queue模拟实现

同样的道理queue也要容纳各种数据,也可以由各种容器作为底层来容纳数据,所以queue也得创建一个模板,并且模板里面也得有两个参数,因为queue是在容器的头部删除数据,在容器的尾部插入数据,所以给第二个参数的缺省值最好是deque,那么这里的代码就如下:

#include<iostream>
#include<vector>
#include<list>
#include<deque>namespace lyk
{template<class T, class continer = deque<T>>class queue{public:private:continer con;};}

💫元素入队列

因为queue插入数据是在容器的尾部插入数据,所以在实现queue的push函数时可以通过调用con的push_back函数来实现,那这里的代码如下:

// 元素入队列
void push(const T& val)
{con.push_back(val);
}

💫元素出队列

queue的pop函数是在容器的头部删除数据所以这里可以调用容器的pop_front函数来实现,那么这里的代码如下:

// 元素出队列
void pop()
{con.pop_front();
}

💫返回队列元素个数

调用内部容器函数来进行实现,那么这里的代码就如下:

// 返回队列元素个数
size_t size()
{return con.size();
}

💫判断队列是否为空

调用内部容器函数来进行实现,那么这里的代码就如下:

// 判断队列是否为空
bool empty()
{return con.empty();
}

💫返回队头元素的引用

调用内部容器函数来进行实现,那么这里的代码就如下:

// 返回队头元素的引用
const T& front()
{return con.front();
}

💫返回队头元素的引用

调用内部容器函数来进行实现,那么这里的代码就如下:

// 返回队头元素的引用
const T& back()
{return con.back();
}

💫queue整体代码

#include<iostream>
#include<vector>
#include<list>
#include<deque>namespace lyk
{template<class T, class continer = deque<T>>class queue{public:// 元素入队列void push(const T& val){con.push_back(val);}// 元素出队列void pop(){con.pop_front();}// 返回队列元素个数size_t size(){return con.size();}// 判断队列是否为空bool empty(){return con.empty();}// 返回队头元素的引用const T& front(){return con.front();}// 返回队头元素的引用const T& back(){return con.back();}private:continer con;};void test_queue(){//bit::queue<int> q;// // vector不能适配//bit::queue<int, vector<int>> q;lyk::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;}}

运行结果:

   🌟结束语

       今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

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

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

相关文章

DataGrip2023配置连接Mssqlserver、Mysql、Oracle若干问题解决方案

1、Mssqlserver连接 本人连的是Sql2008&#xff0c;默认添加时&#xff0c;地址、端口、实例、账号、密码后&#xff0c;测试连接出现错误。 Use SSL&#xff1a;不要勾选 VM option&#xff1a;填写&#xff0c;"-Djdk.tls.disabledAlgorithmsSSLv3, RC4, DES, MD5withR…

【Redis | 第五篇】一篇文章看懂布谷鸟过滤器

文章目录 5.布谷鸟过滤器5.1起源介绍5.2原理5.2.1演示步骤&#xff08;1&#xff09;保存元素&#xff08;两个位置均为空&#xff09;&#xff08;2&#xff09;保存元素&#xff08;其中一个位置被占&#xff09;&#xff08;3&#xff09;保存元素&#xff08;两个位置都被占…

Linux小项目:在线词典开发

在线词典介绍 流程图如下&#xff1a; 项目的功能介绍 在线英英词典项目功能描述用户注册和登录验证服务器端将用户信息和历史记录保存在数据中。客户端输入用户和密码&#xff0c;服务器端在数据库中查找、匹配&#xff0c;返回结果单词在线翻译根据客户端输入输入的单词在字…

轻松玩转Git

轻松玩转Git 快速入门什么是Git为什么要做版本控制安装git Git实战单枪匹马开始干拓展新功能小结 紧急修复bug分支紧急修复bug方案命令总结工作流 上传GitHub第一天上班前在家上传代码初次在公司新电脑下载代码下班回到家继续写代码到公司继续开发在公司约妹子忘记提交代码回家…

CDH6.3.1离线安装

一、从官方文档整体认识CDH 官方文档地址如下&#xff1a; CDH Overview | 6.3.x | Cloudera Documentation CDH是Apache Hadoop和相关项目中最完整、测试最全面、最受欢迎的发行版。CDH提供Hadoop的核心元素、可扩展存储和分布式计算&#xff0c;以及基于Web的用户界面和重…

使用Rust 实现文件批量下载

1.概述 Rust 是一种高效的系统编程语法&#xff0c;具有安全、并发和实用性的特点。本篇文章将通过实例详细介绍如何使用Rust来实现文件的批量下载功能&#xff0c;并提供示例以帮助读者理解。我们的实例将分为四个部分来详细描述&#xff1a;准备环境、创建主函数、实现下载函…

Mysql8.0 数据类型介绍

1&#xff0c;数值类型 1.1 整数类型 TINYINT&#xff1a;微整数&#xff0c;1字节 SMALLINT&#xff1a;小整数&#xff0c;2字节 MEDIUMINT&#xff1a;中等整数&#xff0c;3字节 INT&#xff1a;整数&#xff0c;4字节 BIGINT&#xff1a;大整数&#xff0c;8字节 如…

蓝桥杯备战刷题three(自用)

1.合法日期 #include <iostream> #include <map> #include <string> using namespace std; int main() {map<string,int>mp;int days[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};for(int i1;i<12;i){for(int j1;j<days[i];j){string sto_strin…

江苏双线服务器租用的优势有哪些?

随着互联网的快速发展&#xff0c;服务器也随着科技的发展变得多种多样&#xff0c;其中双线服务器租用格外受大家关注&#xff0c;那么江苏双线服务器租用到底有哪些优势呢&#xff1f; 1.网络环境稳定 江苏双线服务器租用的主要优点就是有着高速稳定的网络环境&#xff0c;双…

P4198 楼房重建题解(线段树, 分治)

题目描述 题面 简要题意&#xff1a; 给你一个长度为 n n n 的序列 a i a_i ai​ ( n ≤ 1 0 5 n \leq 10^5 n≤105)&#xff0c;要求进行 m m m 次操作 ( m ≤ 1 0 5 m \leq 10^5 m≤105) 。操作分两种&#xff1a; 1.单点修改。 2.查询整个序列中有多少个位置 x x x 满…

动态规划(背包理论)-算法题

416. 分割等和子集 题目 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 1&#xff1a; 输入&#xff1a;nums [1,5,11,5] 输出&#xff1a;true 解释&#xff1a;数组可以分割成 [1, …

Vivado Vitis 2023.2 环境配置 Git TCL工程管理 MicroBlaze和HLS点灯测试

文章目录 本篇概要Vivado Vitis 环境搭建Vivado 免费标准版 vs 企业版Vivado Windows 安装Vivado 安装更新 Vivado 工程操作GUI 创建工程打开已有工程从已有工程创建, 重命名工程GUI导出TCL, TCL复原工程TCL命令 Vivado 版本控制BlinkTcl脚本新建导出重建工程纯Verilog BlinkTc…

js处理IOS虚拟键盘弹出后输入框被遮住

​ JS IOS 前言 在项目开发的过程中&#xff0c;在IOS手机端系统下&#xff0c;当对输入框&#xff08;input/textarea&#xff09;进行focus操作时&#xff0c;键盘弹起遮住输入框。 问题描述 从页面底部focus输入框失败从页面中间focus输入框失败 原因 造成上述问题的&…

【MySQL】_自连接与子查询

目录 1. 自连接 2. 子查询&#xff08;嵌套查询&#xff09; 2.1 子查询分类 2.2 单行子查询示例1&#xff1a;查询不想毕业同学的同班同学 2.3 多行子查询示例2&#xff1a;查询语文或英语课程的信息成绩 3. 合并查询 3.1 示例1&#xff1a;查询id3或者名字为英文的课程…

Flutter 处理异步操作并根据异步操作状态动态构建界面的方法FutureBuilder

概述 当界面的内容需要依靠网络请求的数据&#xff0c;就需要处理苦恼的&#xff0c;状态是空&#xff0c;非空的逻辑了&#xff0c;不然页面构建可能会报错&#xff0c;而FutureBuilder提供了一个非常好的解决方法&#xff0c;直接看代码 代码 异步操作函数 即网络请求函数…

[CISCN2019 华北赛区 Day2 Web1]Hack World 1 题目分析与详解

一、分析判断 进入靶机&#xff0c;主页面如图&#xff1a; 主页面提供给我们一条关键信息&#xff1a; flag值在 表flag 中的 flag列 中。 接着我们尝试输入不同的id&#xff0c;情况分别如图&#xff1a; 当id1时&#xff1a; 当id2时&#xff1a; 当id3时&#xff1a; 我…

YOLOv8改进涨点,添加GSConv+Slim Neck,有效提升目标检测效果,代码改进(超详细)

目录 摘要 主要想法 GSConv GSConv代码实现 slim-neck slim-neck代码实现 yaml文件 完整代码分享 总结 摘要 目标检测是计算机视觉中重要的下游任务。对于车载边缘计算平台来说&#xff0c;巨大的模型很难达到实时检测的要求。而且&#xff0c;由大量深度可分离卷积层构…

【Redis | 第三篇】Springboot整合Redis

文章目录 3.Springboot整合Redis3.1Spring Data Redis介绍3.2整合步骤3.2.1导入依赖3.2.2配置redis数据源3.2.3使用RedisTemplate进行操作&#xff08;1&#xff09;创建RedisTemplate Bean&#xff08;2&#xff09;注入RedisTemplate&#xff08;3&#xff09;执行Redis操作&…

C++:常量表达式

C11开始constexpr作为一种声明&#xff0c;为编译器提供了在编译期间确认结果的优化建议&#xff0c;满足部分编译期特性的需求 constexpr和const区别 int b10; const int ab; //运行成功 constexpr int cb; //编译器报错&#xff0c;b的值在编译期间不能确定 const int size1…

面试笔记系列二之java基础+集合知识点整理及常见面试题

目录 Java面向对象有哪些特征&#xff0c;如何应用 Java基本数据类型及所占字节 Java中重写和重载有哪些区别 jdk1.8的新特性有哪些 内部类 1. 成员内部类&#xff08;Member Inner Class&#xff09;&#xff1a; 2. 静态内部类&#xff08;Static Nested Class&#…