C嘎嘎探索篇:栈与队列的交响:C++中的结构艺术

news2024/11/27 5:53:53

C嘎嘎探索篇:栈与队列的交响:C++中的结构艺术

前言:

小编在之前刚完成了C++中栈和队列(stack和queue)的讲解,忘记的小伙伴可以去我上一篇文章看一眼的,今天小编将会带领大家吹奏栈和队列的交响,完成对于他们的模拟实现,使各位更容器去了解它们为什么被叫做容器适配器。
在这里插入图片描述

文章目录

  • C嘎嘎探索篇:栈与队列的交响:C++中的结构艺术
    • 1.stack的模拟实现
      • 1.1.stack类初步书写
      • 1.2.入栈函数push()的实现
      • 1.3.出栈函数pop()的模拟实现
      • 1.4.判空函数empty()的模拟实现
      • 1.5.个数函数size()的模拟实现
      • 1.6.栈顶函数top()的模拟实现
    • 2.小警示
    • 3.queue的模拟实现
      • 3.1.queue类的初步实现
      • 3.2.入队列函数push()的模拟实现
      • 3.3.出队列函数pop()的模拟实现
      • 3.4.取队头函数front()的模拟实现
      • 3.5.取队尾函数back()的模拟实现
      • 3.6.判空函数empty()的模拟实现
      • 3.7.个数函数size()的模拟实现
    • 4.代码展示
      • 4.1.stack
      • 4.2.queue
    • 5.总结

正文:

1.stack的模拟实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先我们就要先实现stack的模拟实现,栈我们以前在数据结构阶段是用顺序表进行实现的,小编此时也是要用一个容器来对其进行实现的,我们在它的众多接口中,不难发现stack是和vector是很像的,所以我们想要实现出stack,就是要给予vector容器进行模拟实现的,当然通过上图我们知道系统是用双端队列(deque)进行实现的,但是比其它,我还是更喜欢使用vector进行模拟实现,小编建议读者朋友在看我模拟实现之前,倘若不了解vector是如何进行使用的,可以先看我之前写过的文章来回顾一下(我先不放上链接了,因为在我写本文之前我还没有发布那篇文章),因为等会我会使用vector的一些接口来帮助我实现出stack,下面开始进入stack类的模拟实现。

1.1.stack类初步书写

我们首先需要先把我们自己写的stack定义在一个命名空间里面,避免和std命名空间里面的stack起冲突,因为stack是一个模版类,所以我们应该用模版类的方式来书写这个类,里面的参数我们对照着标准库书写即可,在我们写完外层以后,就是要书写内层了,此时我们先定一个成员变量,它的类型自然就是Container类型(这个类型可以是vector,可以是list,甚至是string),这个成员变量是为了后续数据的增删而写,下面小编给出这部分代码的书写:

namespace wang   //保存在命名空间里面,避免出现名字冲突,防患于未然
{
  template<class T,class Container = std :: vector<T>>  //默认使用的容器是vector,也可以是list,毕竟也有链式栈的存在
      class stack
      {
        private:
          Container s1;  //s1是为了保存数据的,增删还是需要靠它。
      };
}

1.2.入栈函数push()的实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可能到这里可能很多读者朋友会疑惑我为什么没有书写stack的构造函数,对于对此有疑惑的读者朋友,请好好的去复习一下类和对象的知识,还记着类和对象知识的读者朋友都知道,对于自定义类型的成员变量,编译器是会自己去调用它的构造函数的,如果成员变量没有构造函数的,那么编译器会直接报错,自定义类型需要自己写,当然不写的话系统会调用默认构造函数(默认构造函数有三种,这只是特殊情况之一),所以各位记住这一点,此时s1是vector类型的,它是会自己去调用自己的构造函数的,我们不用瞎操心,下面我们正式堆push()的实现进行讲述。

其实push()函数的实现,我们仅需去复用s1中的接口即可,看看上图stack的构造,我们不难发现此时我们仅需在一个vector类型的尾部插入数据即可,此时我们就可以去调用vector当中的尾插函数即可,根本不用我们自己思考了,所以这就是我前面说stack很好实现的原因,我们仅需套用成员变量的接口即可,这也是我让各位复习一下vector的原因,下面给出代码:

void push(T x)  //此时我们不晓得插入啥类型的元素,这就看我们显示实例化我们想要显示的了
{
    s1.push_back(x);
}

1.3.出栈函数pop()的模拟实现

和小编上面实现入栈函数一样,对于出栈函数,我们也是仅需套用一下s1的接口即可,通过上图我们可以知道此时的出栈操作,对应着的就是把vector对象的尾部删除,所以我们调用尾删函数即可,下面给出代码:

void pop()
{
    s1.pop_back();
}

1.4.判空函数empty()的模拟实现

对于判空函数的模拟实现,也和上面的接口类似,了解vector的朋友都知道,vector里面也是有一个叫做empty()的接口的,我们仅需套用这个接口就好了,下面小编给出代码:

bool empty()
{
    return s1.empty();
}

1.5.个数函数size()的模拟实现

对于它的模拟实现,我们同样也可以套用vector的相关接口,就可以实现这个个数函数,由于难度不大,不再多说给出代码:

int size()
{
    return s1.size();
}

1.6.栈顶函数top()的模拟实现

对于栈顶函数的模拟实现,我们需要先知道栈顶是vector哪个位置的元素,通过上图便可以轻松的看出来栈顶就是vector对象最后一个位置的元素,此时我们仅需返回尾部元素即可,此时我们可以套用vector中的back接口,这个接口我虽然没讲,它的功能就是返回vector最后一个位置的元素,名字其实就可以知晓了。下面小编给出代码写法:

T top()
{
    return s1.back();
}

以上便就是对于stack的模拟实现,是不是灰常的简单,小编当时在经历完某几个容器的模拟实现之后,这一模拟实现stack,就感到了一阵舒爽,我们仅需疯狂的套用接口就好了,剩下的全靠编译器的调用了,等会queue的讲解也会非常的舒服,不过在讲述queue之前,小编先给各位说一个小的知识点,避免读者朋友踩坑。

2.小警示

对于接下来无论是容器还是适配器的模拟实现,各位读者朋友千万不要让模版的声明和定义分离,我忘记我模版说没说过了,对于模板类型的类和函数,它们的声明和定义是不可以去分离的,这涉及到了分离编译的知识,这部分的知识点小编通过一个图带各位简单的了解下,更为详细的知识我会在模版进阶文章进行讲述,其中的过程通过下图便可以知晓为什么模版的声明和定义是无法分离的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以我们在进行模拟实现的时候,直接把声明和定义放在一个头文件即可,这个知识点要牢记,防止一些读者朋友犯迷糊。

3.queue的模拟实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在讲述这个小警示以后,紧接着我们就要开始进入queue的模拟实现了,相信看完前文的stack的模拟实现后,各位应该对于queue的模拟实现也会信心满满,因为queue的接口中设计了一端进一端出,因此此时我们用vector封装的话效率会变的很低,根据以前我们数据机构队列的实现的检验来看,用双链表是一个不错的选择,而恰好我们之前list就是一个典型的双链表结构,所以此时我们就是用list来帮助我们实现queue的模拟实现,下面我们就进入queue的模拟实现。

3.1.queue类的初步实现

首先我们需要先完成queue的外部的书写,此时和stack一样,为了防止命名冲突,我们需要把它放置在我们自己的命名空间内,然后完成一个模板类的书写,之后我们再和标准库的queue一样书写模版参量,之后我们在写一个Container类型的对象就好了,把它作为我们的成员变量,通过它实现出队列的增删等操作,下面给出这层外套:

namespace wang
{
    template<class T,class Container = list<T>>
        class queue
        {
          private:
            Container s1;
        };
}

3.2.入队列函数push()的模拟实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于入队列函数,此时我们需要按照队列的结构来对于list对象接口进行合理使用,此时我们知道入队列是从队尾入,所以此时我们需要用到list里面的尾插接口来帮助我们实现这个功能,下面小编给出这个代码的书写:

void push(T x)
{
    s1.push_back(x);
}

3.3.出队列函数pop()的模拟实现

对于出队列函数,我们依照队列的结构,发现它是从队头进行出队列操作,所以此时我们就要借助list对象的头删函数来帮助我们完成出队列操作,下面小编给出这个代码的书写:

void pop()
{
    s1.poo_front();
}

3.4.取队头函数front()的模拟实现

这个函数的功能名字就可以体现出来,此时我们如果想要取出队头,就需要知道是s1的一个我也没讲过的接口,front()接口,它的功能就是取出双链表第一个有效结点的元素,所以它正好就可以取出队头元素,下面给出代码书写:

T front()
{
    return s1.front();
}

3.5.取队尾函数back()的模拟实现

这个函数的功能同样通过名字就可以体现出来,此时我们想要取出队尾,就需要知道s1的back()接口,他和vector一样,都是取出最后一个位置的元素,用它便可以取出队尾的元素,下面给出代码:

T back()
{
    return s1.back();
}

3.6.判空函数empty()的模拟实现

对于判空函数,无非就是判断队列里面是否为空,无非就是检查成员变量是否为空,此时我们仅需调用list对象的判空函数即可,下面小编给出代码:

bool empty()
{
    return s1.empty();
}

3.7.个数函数size()的模拟实现

我们如果想要知道队列里面有几个有效元素,直到成员对象里面有几个有效元素即可,此时我们仅需套用它的size()函数即可,下面给出代码:

int size()
{
    return s1.size();
}

以上便就是小编对于queue的模拟实现,此时此刻的你是不是感受到了“套娃”的魅力,对于适配器的模拟实现,我们仅需知道合适的容器就好了,剩下的就是无限的套用,只能说用起来十分的舒适,容器的模拟实现我认为是很复杂的,这就是我到现在都没有书写容器的模拟实现的原因(咳咳其实也是懒的写),下面我把这些代码整合起来来帮助各位知晓一个完整的模拟实现。

4.代码展示

4.1.stack

namespace wang
{
	template<class T,class Container = std :: vector<T>>
	class stack
	{
	public:
		void push(T x)
		{
			s1.push_back(x);
		}
		
		void pop()
		{
			s1.pop_back();
		}

		bool empty()
		{
			return s1.empty();
		}

		int size()
		{
			return s1.size();
		}

		T top()
		{
			return s1.back();
		}
	private:
		Container s1;
	};
}

4.2.queue

namespace wang
{
	template<class T,class Comtainer = std :: list<T> >
	class queue
	{
	public:
		void push(T x)
		{
			s1.push_back(x);
		}

		void pop()
		{
			s1.pop_front();
		}

		int size()
		{
			return s1.size();
		}

		T front()
		{
			return s1.front();
		}

		T back()
		{
			return s1.back();
		}

		bool empty()
		{
			return s1.empty();
		}


	private:
		Comtainer s1;
	};
}

`

5.总结

此时此刻小编就完成了栈和队列的模拟实现,是不是很轻松,这直接套用别的容器接口的感觉就是舒服,如果容器的模拟实现也是这样该多好(当然不可能),希望后来的我可以完成各种容器的模拟实现文章的书写,感觉写一篇相关类型的文章可以帮助我更好的成长,如果文章有错误,可以在评论区点出,我会定期的回复读者朋友,那么各位大佬们,我们下一篇文章见啦!
在这里插入图片描述

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

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

相关文章

Postman设置接口关联,实现参数化

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 postman设置接口关联 在实际的接口测试中&#xff0c;后一个接口经常需要用到前一个接口返回的结果&#xff0c; 从而让后一个接口能正常执行&#xff0c;这…

大模型的RAG微调与Agent:提升智能代理的效率与效果

目录 ​编辑 引言 RAG模型概述 检索阶段 生成阶段 RAG模型的微调 数据集选择 损失函数设计 微调策略 超参数调整 RAG模型在智能代理中的应用 客户服务 信息检索 内容创作 决策支持&#xff1a; 结论 引言 在人工智能的快速发展中&#xff0c;大型预训练模型&a…

前端---CSS(部分用法)

HTML画页面--》这个页面就是页面上需要的元素罗列起来&#xff0c;但是页面效果很差&#xff0c;不好看&#xff0c;为了让页面好看&#xff0c;为了修饰页面---》CSS CSS的作用&#xff1a;修饰HTML页面 用了CSS之后&#xff0c;样式和元素本身做到了分离的效果。---》降低了代…

【R语言管理】Pycharm配置R语言及使用Anaconda管理R语言虚拟环境

目录 使用Anaconda创建R语言虚拟环境1. 安装Anaconda2. 创建R语言虚拟环境 Pycharm配置R语言1. 安装Pycharm2. R Language for IntelliJ插件 参考 使用Anaconda创建R语言虚拟环境 1. 安装Anaconda Anaconda的安装可参见另一博客-【Python环境管理工具】Anaconda安装及使用教程…

互联网视频推拉流EasyDSS视频直播点播平台视频转码有哪些技术特点和应用?

视频转码本质上是一个先解码再编码的过程。在转码过程中&#xff0c;原始视频码流首先被解码成原始图像数据&#xff0c;然后再根据目标编码标准、分辨率、帧率、码率等参数重新进行编码。这样&#xff0c;转换前后的码流可能遵循相同的视频编码标准&#xff0c;也可能不遵循。…

Linux Shell 脚本题目集

1、执行 ping 命令对指定主机进行测试&#xff0c;以确定该主机是否处于存活状态并输出相应结果。 #!/bin/bashread -p "请输入主机号&#xff1a;" pc # 读取用户输入的主机号if [ -z "$pc" ];then # 检查用户输入是否为空echo "主…

使用ENSP实现默认路由

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable 进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为2.2.2.1/24 ip address 2.2.2.1 24进入g0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置为1.…

【vue3实现微信小程序】每日专题与分页跳转的初步实现

快速跳转&#xff1a; 我的个人博客主页&#x1f449;&#xff1a;Reuuse博客 新开专栏&#x1f449;&#xff1a;Vue3专栏 参考文献&#x1f449;&#xff1a;uniapp官网 免费图标&#x1f449;&#xff1a;阿里巴巴矢量图标库 ❀ 感谢支持&#xff01;☀ 前情提要 &#x…

小程序-基于java+SpringBoot+Vue的网上花店微信小程序设计与实现

项目运行 1.运行环境&#xff1a;最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境&#xff1a;IDEA&#xff0c;Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境&#xff1a;Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…

Opencv+ROS实现颜色识别应用

目录 一、工具 二、原理 概念 本质 三、实践 添加发布话题 主要代码 四、成果 五、总结 一、工具 opencvros ubuntu18.04 摄像头 二、原理 概念 彩色图像&#xff1a;RGB&#xff08;红&#xff0c;绿&#xff0c;蓝&#xff09; HSV图像&#xff1a;H&#xff0…

解决 java -jar 报错:xxx.jar 中没有主清单属性

问题复现 在使用 java -jar xxx.jar 命令运行 Java 应用程序时&#xff0c;遇到了以下错误&#xff1a; xxx.jar 中没有主清单属性这个错误表示 JAR 文件缺少必要的启动信息&#xff0c;Java 虚拟机无法找到应用程序的入口点。本文将介绍该错误的原因以及如何通过修改 pom.xm…

JavaWeb——SpringBoot原理

10.1. 配置优先级 10.1.1. 配置文件 properties > yml(推荐) > yaml 10.1.2. Java系统属性、命令行参数 命令行参数 > Java系统属性 > 配置文件 10.2. Bean管理 10.2.1. 手动获取bean ApplicationContext&#xff0c;IOC容器对象 10.2.2. bean作用域 10.2.3.…

【AI绘画】Midjourney进阶:色调详解(上)

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;Midjourney中的色彩控制为什么要控制色彩&#xff1f;为什么要在Midjourney中控制色彩&#xff1f; &#x1f4af;色调白色调淡色调明色调 &#x1f4af…

STM32F103外部中断配置

一、外部中断 在上一节我们介绍了STM32f103的嵌套向量中断控制器&#xff0c;其中包括中断的使能、失能、中断优先级分组以及中断优先级配置等内容。 1.1 外部中断/事件控制器 在STM32f103支持的60个可屏蔽中断中&#xff0c;有一些比较特殊的中断&#xff1a; 中断编号13 EXTI…

【Vue3+Pinia】Vue新一代状态管理器Pinia

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【消息序列】详解(7):剖析回环模式--设备测试的核心利器

目录 一、概述 1.1. 本地回环模式 1.2. 远程环回模式 二、本地回环模式&#xff08;Local Loopback mode&#xff09; 2.1. 步骤 1&#xff1a;主机进入本地环回模式 2.2. 本地回环测试 2.2.1. 步骤 2a&#xff1a;主机发送HCI数据包并接收环回数据 2.2.2. 步骤 2b&…

大厂也在用的分布式链路追踪:TraceIdFilter + MDC + Skywalking

痛点 查线上日志时&#xff0c;同一个 Pod 内多线程日志交错&#xff0c;很难追踪每个请求对应的日志信息。 日志收集工具将多个 Pod 的日志收集到同一个数据库中后&#xff0c;情况就更加混乱不堪了。 解决 TraceId MDC 前端每次请求时&#xff0c;添加 X-App-Trace-Id 请…

leetcode - 2116. Check if a Parentheses String Can Be Valid

Description A parentheses string is a non-empty string consisting only of ‘(’ and ‘)’. It is valid if any of the following conditions is true: It is ().It can be written as AB (A concatenated with B), where A and B are valid parentheses strings.It ca…

如何启动 Docker 服务:全面指南

如何启动 Docker 服务:全面指南 一、Linux 系统(以 Ubuntu 为例)二、Windows 系统(以 Docker Desktop 为例)三、macOS 系统(以 Docker Desktop for Mac 为例)四、故障排查五、总结Docker,作为一种轻量级的虚拟化技术,已经成为开发者和运维人员不可或缺的工具。它允许用…

安装MySQL服务

安装版本MySQL8的安装包 安装界面 在这里选择MySQL中的Server only 只安装服务器端 如果选择custom需要如下图 进入配置导向&#xff0c;点击ready to configure&#xff0c;点击next即可 采用默认形式 执行成功后&#xff0c;会出现自动选择项 点击next然后再点击Finish 启动…