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

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.总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Xcode15(iOS17.4)打包的项目在 iOS12 系统上启动崩溃

0x00 启动崩溃 崩溃日志&#xff0c;只有 2 行&#xff0c;看不出啥来。 0x01 默认配置 由于我开发时&#xff0c;使用的 Xcode 14.1&#xff0c;打包在另外一台电脑 Xcode 15.3 Xcode 14.1 Build Settings -> Asset Catalog Compliter - Options Xcode 15.3 Build S…

【Python爬虫实战】深入解析 Scrapy:从阻塞与非阻塞到高效爬取的实战指南

&#x1f308;个人主页&#xff1a;易辰君-CSDN博客 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、阻塞和非阻塞 &#xff08;一&#xff09;阻塞 &#xff08;二&#xff09;非阻塞 二、Scrapy的工作…

01 [51单片机 PROTEUS仿真设计]基于温度传感器的恒温控制系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 五个按键&#xff0c;分别为启动按键&#xff0c;则LCD1602显示倒计时&#xff0c;音乐播放 设置按键&#xff0c;可以设置倒计时的分秒&#xff0c;然后加减按键&#xff0c;还有最后一个暂停音乐…

途普科技企业知识中台完成华为昇思MindSpore技术认证

近日&#xff0c;北京途普科技有限公司&#xff08;以下简称“途普科技”&#xff09;作为华为昇腾大模型方向的应用软件伙伴&#xff0c;核心产品企业知识中台已成功与华为AI框架昇思MindSpore完成相互兼容性认证。这一成就标志着途普科技在AI领域与华为的合作进一步加深&…

shodan(7)

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

MYSQL 表的增删改查(上)

目录 1.新增数据 2.查询数据 一般查询 去重查询 排序查询 关于NULL 条件查询 分页查询 1.新增数据 语法&#xff1a;insert into 表名[(字段1&#xff0c;字段2...)] values (值&#xff0c;值....); 插入一条新数据行&#xff0c;前面指定的列&#xff0c;要与后面v…

海康面阵、线阵、读码器及3D相机接线说明

为帮助用户快速了解和配置海康系列设备的接线方式&#xff0c;本文将针对海康面阵相机、线阵相机、读码器和3D相机的主要接口及接线方法进行全面整理和说明。 一、海康面阵相机接线说明 海康面阵相机使用6-pin P7接口&#xff0c;其功能设计包括电源输入、光耦隔离信号输入输出…

Java多线程八股(三)一>多线程环境使用哈希表和ArrayList

目录&#xff1a; 一.多线程环境使用ArrayList&#xff1a; 二.多线程使用哈希表&#xff1a; 一.多线程环境使用ArrayList&#xff1a; 首先我们知道&#xff0c;Vector, Stack, HashTable, 是线程安全的(但是不建议用), 其他的集合类不是线程安全的 &#xff0c;下面是…

TCP IP协议和网络安全

传输层的两个协议&#xff1a; 可靠传输 TCP 分段传输 建立对话&#xff08;消耗系统资源&#xff09; 丢失重传netstat -n 不可靠传输 UDP 一个数据包就能表达完整的意思或屏幕广播 应用层协议&#xff08;默认端口&#xff09;&#xff1a; httpTCP80 网页 ftpTCP21验证用户身…

Webpack前端工程化进阶系列(二) —— HMR热模块更新(图文+代码)

前言 之前更新过一篇Webpack文章:Webpack入门只看这一篇就够了(图文代码)&#xff0c;没想到颇受好评&#xff0c;很快就阅读量就破万了hhh&#xff0c;应读者私信的要求&#xff0c;决定继续更新Webpack进阶系列的文章&#xff01; 进入今天的主题 —— HMR 热模块替换(HotM…

第三讲 架构详解:“隐语”可信隐私计算开源框架

目录 隐语架构 隐语架构拆解 产品层 算法层 计算层 资源层 互联互通 跨域管控 本文主要是记录参加隐语开源社区推出的第四期隐私计算实训营学习到的相关内容。 隐语架构 隐语架构拆解 产品层 产品定位&#xff1a; 通过可视化产品&#xff0c;降低终端用户的体验和演…

C# 结构体

文章目录 前言一、结构体的定义与基本使用&#xff08;一&#xff09;定义结构体&#xff08;二&#xff09;结构体的使用示例 二、C# 结构的特点&#xff08;一&#xff09;丰富的成员类型&#xff08;二&#xff09;构造函数相关限制与特性&#xff08;三&#xff09;继承方面…

Easyexcel(7-自定义样式)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09;Easyexcel&#xff08;5-自定义列宽&#xff09;Easyexcel&#xff08;6-单…

【c语言】文件操作详解 - 从打开到关闭

文章目录 1. 为什么使用文件&#xff1f;2. 什么是文件&#xff1f;3. 如何标识文件&#xff1f;4. 二进制文件和文本文件&#xff1f;5. 文件的打开和关闭5.1 流和标准流5.1.1 流5.1.2 标准流 5.2 文件指针5.3 文件的打开和关闭 6. 文件的读写顺序6.1 顺序读写函数6.2 对比一组…

2024-11-23 队列及顺序存储实现

2.3.1 队列及顺序存储实现 与堆栈类似&#xff0c;队列也是一种受限制的线性表。 其实我们在日常生活中经常会碰到排队。我们来观察一下&#xff0c;什么叫做队列&#xff0c;里面有两个最基本的操作&#xff0c;一个叫做入队&#xff0c;一个叫做出队。也就是你能加入这个队…

卷积神经网络学习记录

目录 神经网络基础定义&#xff1a; 基本组成部分 工作流程 卷积层&#xff08;卷积定义&#xff09;【CONV】&#xff1a; 卷积层&#xff08;Convolutional Layer&#xff09; 特征提取&#xff1a;卷积层的主要作用是通过卷积核&#xff08;或滤波器&#xff09;运算提…

数据结构初阶---复杂度

一、数据结构前言 1.数据结构与算法 数据结构(Data Structure)&#xff1a;是计算机组织、存储数据的一种方式&#xff0c;指相互之间存在一种或多种特定关系的数据元素的集合。 算法(Algorithm)&#xff1a;就是定义良好的计算过程&#xff0c;他取一个或一组的值为输入&am…

二叉树的层次遍历

二叉树的层次遍历 题目 https://leetcode-cn.com/problems/binary-tree-level-order-traversal/ 描述 给你一个二叉树,请你返回其按 层次遍历 得到的节点值(即逐层地,从做到右访问所有节点) 代码实现 通过两个数组来交替打印 class Solution(object):def levelOrder

网络安全中的数据科学如何重新定义安全实践?

组织每天处理大量数据&#xff0c;这些数据由各个团队和部门管理。这使得全面了解潜在威胁变得非常困难&#xff0c;常常导致疏忽。以前&#xff0c;公司依靠 FUD 方法&#xff08;恐惧、不确定性和怀疑&#xff09;来识别潜在攻击。然而&#xff0c;将数据科学集成到网络安全中…

【Linux系统】—— 基本指令(四)

【Linux系统】—— 基本指令&#xff08;三&#xff09; 1「find」指令2 「grep」指令2.1 初识「grep」指令2.2 「grep」指令 选项 3 打包压缩基本知识4 「zip / unzip」指令5「tar」命令6 文件互传6.1 Linux 与 Windows 互传6.1.1 Linux向Windows传输6.1.2 Windows向Linux传输…