【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.hqwc.cn/news/498195.html

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

相关文章

基础!!!吴恩达deeplearning.ai:卷积层

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 文章目录 回顾——密集层 Dense Layer卷积层 Convolutional Neural Network定义优势具体说明心电图卷积层搭建 到目前为止&#xff0c;你使用的所有神经网络层都是密集层类型&#xff0c;这…

ICVQUANTUMCHINA报告:《2024全球量子计算产业发展展望》

2月20日&#xff0c;《2024量子计算产业发展展望》的中文版报告通过光子盒官方平台发布&#xff0c;英文版报告通过ICV官方平台发布。 英文版报告获取地址&#xff1a; https://www.icvtank.com/newsinfo/897610.html 在过去的一年里&#xff0c;光子盒与您一同见证了全球量子…

幻兽帕鲁专用服务器搭建之Linux部署配置教程

大家好我是飞飞&#xff0c;上一期我分享了Windows系统的幻兽帕鲁服务器搭建教程。因为幻兽帕鲁这游戏对服务器的配置有一定的要求&#xff0c;很多小伙伴就寻思用Linux系统搭建占用会不会小一点&#xff1f;有计算机基础的小伙伴都知道Linux系统和Windows系统相比&#xff0c;…

探索前景:机器学习中常见优化算法的比较分析

目录 一、介绍 二、技术背景 三、相关代码 四、结论 一、介绍 优化算法在机器学习和深度学习中至关重要&#xff0c;可以最小化损失函数&#xff0c;从而改善模型的预测。每个优化器都有其独特的方法来导航损失函数的复杂环境以找到最小值。本文探讨了一些最常见的优化算法&…

前端Ajax获取当前外网IP地址并通过腾讯接口解析地理位置

目录 一、获取访问端IP地址 二、可用的IP获取接口 1、韩小韩IP获取接口&#xff1a; 2、ipify API 附3、失败的太平洋接口 三、腾讯位置服务-IP位置查询接口 一、获取访问端IP地址 原计划使用后端HttpServletRequest 获取访问端的IP地址&#xff0c;但在nginx和堡垒机等阻…

Python多功能课堂点名器、抽签工具

一、问题缘起 去年&#xff0c;ChatGPT浪潮袭来&#xff0c;我懂简单的Python基础语法&#xff0c;又有一些点子&#xff0c;于是借助于人工智能问答工具&#xff0c;一步一步地制作了一个点名器&#xff0c;也可以用于抽签。当时&#xff0c;我已经设计好页面和基础的功能&am…

Leetcode 第 385 场周赛题解

Leetcode 第 385 场周赛题解 Leetcode 第 385 场周赛题解题目1&#xff1a;3042. 统计前后缀下标对 I思路代码复杂度分析 题目2&#xff1a;3043. 最长公共前缀的长度思路代码复杂度分析 题目3&#xff1a;3044. 出现频率最高的质数思路代码复杂度分析 题目4&#xff1a;3045. …

【EFK】基于K8S构建EFK+logstash+kafka日志平台

基于K8S构建EFKlogstashkafka日志平台 一、常见日志收集方案1.1、EFK1.2、ELK Stack1.3、ELK filbeat1.4、其他方案 二、EFK组件介绍2.1、Elasticsearch组件2.2、Filebeat组件【1】 Filebeat和beat关系【2】Filebeat是什么【3】Filebeat工作原理【4】传输方案 2.3、Logstash组件…

本届挑战赛季军方案:基于图网络及LLM AGENT的微服务系统异常检测和根因定位方法

aiboco团队荣获本届挑战赛季军。该团队来自亿阳信通。 方案介绍 本届挑战赛采用开放式赛题&#xff0c;基于建行云龙舟运维平台的稳定性工具和多维监控系统&#xff0c;模拟大型的生活服务APP的生产环境&#xff0c;提供端到端的全链路的日志、指标和调用链数据。参赛队伍在组…

操作系统:IO管理概述

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;OS从基础到进阶 &#x1f3c6;&#x1f3c6;本文完整PDF源文件请翻阅至文章底部下载。&#x1f3c6;&#x1f3c6; 1 I/O设备的基本概念与分类1.1 总览1.2 什么是IO设备1.3 IO设备的分类1…

yolov8涨点技巧,添加SwinTransformer注意力机制,提升目标检测效果

目录 摘要 SwinTransformer原理 代码实现 YOLOv8详细添加步骤 ymal文件内容 one_swinTrans three_swinTrans 启动命令 完整代码分享 摘要 Swin Transformer通过引入创新的分层注意力机制展现了其架构的独特性&#xff0c;该机制通过将注意力区域划分为块并在这些块内执…

NutUI + taro +vue 开发遇到的问题 使用popup组件 内部元素滚动遇到的的问题

1 popup 弹出内容时 弹出的框内元素数据很长需要滚动时 本地可以正常滚动 打包成小程序后无法滚动 如这样的免责条款内容 代码如下 解决办法 1 把2处的单位换成百分比 弹框能滚动但是 是popup 里面所有的元素都一起滚动 导致标题都滚走了 2 scroll-y 改成&#xff1a; :scrol…