【C++】stack、queue模拟实现

💗个人主页💗
⭐个人专栏——C++学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

导读

1. stack和queue的底层

1.1 stack

1.2 queue

2. 什么是适配器

3. 常见适配器

4. stack具体实现

4.1 成员变量

4.2 push函数

4.3 pop函数

4.4 size函数

4.5 empty函数

4.6 top函数 

5. stack实现完整代码 

5.1 stack.h

5.2 test.cpp

6. queue具体实现

6.1 成员变量

6.2 push函数

6.3 pop函数

6.4 size函数

6.5 empty函数

6.6 front和back函数

7. queue实现完整代码

7.1 queue.h

7.2 test.cpp


导读

我们上次了解了stack和queue的一些基本使用,今天我们就来试着实现一下。

1. stack和queue的底层

1.1 stack

C++中的stack通常是由deque(双端队列)或vector(动态数组)实现的。这是因为deque和vector都提供了方便的尾部插入和删除操作,符合stack的后进先出(LIFO)原则。

  • 如果使用deque实现stack,那么每次将元素推入栈顶时,将元素插入到deque的尾部;而每次从栈顶弹出元素时,从deque的尾部删除元素。这样可以快速实现栈的操作,并保持栈的后进先出的特性。
  • 如果使用vector实现stack,那么每次将元素推入栈顶时,将元素插入到vector的尾部;而每次从栈顶弹出元素时,从vector的尾部删除元素。类似地,这样也可以实现栈的操作,但由于vector是动态数组,所以在元素数量超过vector的当前容量时,可能需要重新分配内存并复制元素,这可能导致性能损失。

C++的标准库中还提供了适配器(adapter)stack,它基于deque或vector实现,隐藏了底层容器的实现细节,并提供了方便的栈操作接口。这样可以在不直接操作底层容器的情况下使用stack,使代码更加简洁和易读。

需要注意的是,由于stack只提供了后进先出的操作,没有提供随机访问元素的能力,因此不支持迭代器遍历。如果需要遍历栈中的元素,可以通过反复弹出栈顶元素并处理,直到栈为空。

1.2 queue

queue是一个基于适配器模式实现的容器适配器。它是一个先进先出(FIFO)的数据结构,内部使用一个底层容器来存储元素。

默认情况下,queue使用deque作为其底层容器。deque是一种双向队列,支持快速在头部和尾部进行插入和删除操作,因此适合作为queue的底层容器。

通过适配器的方式,queue将底层容器的接口封装起来,提供了一组符合先进先出原则的操作。这使得使用queue变得更加方便、简洁,并且可以灵活地选择底层容器类型,以满足特定的需求。如果需要自定义底层容器,可以通过模板参数来指定特定的容器类型。

2. 什么是适配器

适配器(Adapter)是一种设计模式,用于将一个类的接口转换为客户端所期望的另一个接口。适配器模式允许原本不兼容的类能够一起工作。

适配器通常有两种类型:

  1. 类适配器:使用多重继承的方式,将被适配类的接口转换为目标接口。适配器继承被适配类,并实现目标接口。
  2. 对象适配器:通过组合的方式,将适配器对象与被适配对象关联起来,将被适配类的接口转换为目标接口。适配器实现目标接口,并在内部持有被适配对象的实例。

适配器模式常用于以下情况:

  • 当需要使用一个已经存在的类,但其接口与现有代码不兼容时,可以使用适配器模式将其接口转换为目标接口。
  • 当需要复用一些现有类,但是这些类不具备与所需接口匹配的方法时,可以使用适配器模式添加额外的逻辑,实现所需接口。

总结来说,适配器模式可以让原本不兼容的类能够一起工作,实现接口转换和兼容性。

3. 常见适配器

以下是C++中的一些常见适配器:

  1. stack:适配器stack用于将deque或vector等底层容器实现为后进先出(LIFO)的栈。

  2. queue:适配器queue用于将deque或list等底层容器实现为先进先出(FIFO)的队列。

  3. priority_queue:适配器priority_queue用于将vector或deque等底层容器实现为优先级队列,其中元素按照一定的优先级顺序排列。

  4. stack和queue的适配器:C++标准库还提供了两个适配器,即stack和queue,它们可以使用deque、list或vector等底层容器作为实现。这样可以根据需求选择不同的底层容器,以满足不同的性能要求。

这些适配器通过封装底层容器的实现,提供了一种统一的接口,使得程序员可以方便地使用这些数据结构和算法,而不需要关心底层容器的具体实现细节。此外,适配器还提供了简化和抽象的功能,使得代码更加易读和可维护。

4. stack具体实现

4.1 成员变量

    //第二个模板参数给一个缺省值(只能从右往左给)
	template<class T, class Container = vector<T>>
	class stack
	{
	private:
		Container _con;
	};

Container表示用于存储栈元素的容器类型,默认情况下使用vector<T>作为容器类型。可以通过实例化stack类时指定具体的容器类型。

通过使用模板类stack,可以实例化不同类型元素的栈,并且可以灵活选择底层容器类型。例如,可以创建一个存储整数类型的栈:stack<int>,默认使用vector<int>作为容器。也可以创建一个存储字符串类型的栈:stack<string, list<string>>,使用list<string>作为容器。

4.2 push函数

		void push(const T& x)
		{
			_con.push_back(x);
		}

具体来说,这个函数使用了_con容器的push_back()成员函数,将元素x插入到容器的尾部。

每次调用push()函数,新元素都会被添加到底层容器的尾部,实现了栈的特性:后进先出(LIFO)。

4.3 pop函数

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

pop函数使用了底层容器_conpop_back()成员函数,它会从底层容器的末尾弹出一个元素。

4.4 size函数

		size_t size()
		{
			return _con.size();
		}

 这个函数使用了_con容器的size()成员函数,它会返回底层容器的元素个数。

4.5 empty函数

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

 

这是stack类中的empty函数的实现。它执行的操作是判断底层容器是否为空。

具体来说,这个函数使用了_con容器的empty()成员函数,它会检查底层容器是否为空。如果底层容器为空,返回true,否则返回false

4.6 top函数 

		const T& top()
		{
			return _con.back();
		}

top函数使用了底层容器_conback()成员函数,它返回底层容器中的最后一个元素,即栈中的顶部元素。

5. stack实现完整代码 

5.1 stack.h

#pragma once
#include <iostream>
using namespace std;
#include <vector>

namespace Mystack
{
	//第二个模板参数给一个缺省值(只能从右往左给)
	template<class T, class Container = vector<T>>
	class stack
	{
	public:

		void push(const T& x)
		{
			_con.push_back(x);
		}

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

		size_t size()
		{
			return _con.size();
		}

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

		const T& top()
		{
			return _con.back();
		}
	private:
		Container _con;
	};

}

5.2 test.cpp

#include "stack.h"

void test_stack()
{
	Mystack::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;
}

int main()
{
	test_stack();

	return 0;
}

6. queue具体实现

6.1 成员变量

	template<class T, class Container = deque<T>>
	class queue
	{
	private:
		Container _con;
	};

这是一个queue类的模板定义。它使用一个模板参数T来表示元素的类型,并使用一个模板参数Container来表示底层容器的类型,默认为deque<T>。

在这个queue类中,私有成员变量_con表示底层容器,用于存储元素。它的类型是通过模板参数Container来确定的,默认情况下是deque<T>类型。

这个模板类定义了一个基本的队列数据结构,使得用户可以方便地在底层容器上进行队列操作,例如入队、出队、获取队头元素等。具体的队列操作实现可以通过对底层容器的操作来完成。

6.2 push函数

		void push(const T& x)
		{
			_con.push_back(x);
		}

这个函数使用了_con容器的push_back()成员函数,将元素x插入到容器的尾部。在deque容器中,push_back()函数的时间复杂度为常数时间,可以快速地将元素添加到容器的尾部。

6.3 pop函数

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

 这个函数使用了_con容器的pop_front()成员函数,它会删除底层容器的第一个元素。在deque容器中,pop_front()函数的时间复杂度为常数时间,因此可以快速地删除第一个元素。

6.4 size函数

		size_t size()
		{
			return _con.size();
		}

这是queue类中的size函数的实现。它执行的操作是返回底层容器的元素个数。

具体来说,这个函数使用了_con容器的size()成员函数,它会返回底层容器的元素个数。在deque容器中,size()函数的时间复杂度为常数时间,因此可以快速地获取元素个数。

6.5 empty函数

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

这是queue类中的empty函数的实现。它执行的操作是判断底层容器是否为空。

具体来说,这个函数使用了_con容器的empty()成员函数,它会检查底层容器是否为空。如果底层容器为空,返回true,否则返回false

6.6 front和back函数

		const T& front()
		{
			return _con.front();
		}

		const T& back()
		{
			return _con.back();
		}

 这是queue类中的frontback函数的实现。它们分别返回队列的第一个元素和最后一个元素的引用。

具体来说,front函数使用了底层容器_confront()成员函数,它会返回底层容器的第一个元素的引用。back函数则使用了_conback()成员函数,它返回底层容器的最后一个元素的引用。

这样,可以通过调用front()back()函数来访问队列的第一个元素和最后一个元素,而不需要直接操作底层容器。

7. queue实现完整代码

7.1 queue.h

#pragma once
#include <iostream>
using namespace std;
#include<deque>

namespace Myqueue
{
	template<class T, class Container = deque<T>>
	class queue
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}

		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:
		Container _con;
	};
}

7.2 test.cpp

#include "queue.h"

void test_queue1()
{
	Myqueue::queue<int> q;
	q.push(1);
	q.push(2);

	cout << q.front() << " ";
	q.pop();

	q.push(3);
	q.push(4);

	while (!q.empty())
	{
		cout << q.front() << " ";
		q.pop();
	}
	cout << endl;
}
int main()
{
	test_queue1();

	return 0;
}

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

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

相关文章

wms海外仓系统有哪些?选择的时候怎么避坑

虽然说wms海外仓系统能够在很大程度上提升海外仓的经营效率&#xff0c;但是如果在选择wms海外仓系统的时候没有慎重考虑&#xff0c;也是非常容易踩坑的。 这样不只是不能提升自己海外仓的效率&#xff0c;反倒是浪费了大量的预算和精力&#xff0c;这就得不偿失了。今天我们…

【Three.js】知识梳理二十三:Three.js与其他WebGL库与框架对比

在WebGL开发中&#xff0c;Three.js是一个非常流行的库&#xff0c;它简化了3D图形的创建和渲染过程。然而&#xff0c;市场上还有许多其他的WebGL库&#xff0c;如 Babylon.js、PlayCanvas、PIXI.js 和 Cesium&#xff0c;它们也有各自的特点和优势。本文将对Three.js 与这些常…

早知 121私人导航升级新版本, 第一次使用原生dialog标签。

早知121项目介绍说明 早知121 - 一个快速创建私人导航网站。 用途&#xff1a; 创建个人的工作导航&#xff0c;收集常用网址&#xff0c;可贡献给同事。创建个人垂直领域导航 优点&#xff1a; - 不需懂技术&#xff0c;不用维护服务器&#xff0c;维护私人导航收藏站。 网…

贝壳找房: 为 AI 平台打造混合多云的存储加速底座

贝壳机器学习平台的计算资源&#xff0c;尤其是 GPU&#xff0c;主要依赖公有云服务&#xff0c;并分布在不同的地理区域。为了让存储可以灵活地跟随计算资源&#xff0c;存储系统需具备高度的灵活性&#xff0c;支持跨区域的数据访问和迁移&#xff0c;同时确保计算任务的连续…

2024网络安全学习路线 非常详细 推荐学习

关键词&#xff1a;网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 首先咱们聊聊&#xff0c;学习网络安全方向通常会有哪些问题 1、打基础时间太长 学基础花费很长时间&#xff0c;光语言都有几门&#xff0c;有些人会倒在学习 linux 系统及命令的路上&#…

ROC曲线和AUC,推荐系统中常用AUC作为排序模型的评估指标

文章目录 1、ROC曲线2、AUC计算及代码 1、ROC曲线 在不同的应用任务中&#xff0c;我们可根据任务需求来采用不同的截断点。如果我们更重视“查准率”&#xff0c;则可选择排序中靠前的位置进行截断&#xff1b;如果更重视“查全率”&#xff0c;则可选择靠后的位置进行截断。…

C++怎么根据变量名称返回变量的值?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 有点好奇你这么做是为了什么。…

184.二叉树:二叉树的最近公共祖先(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:// 函数用于寻找二叉树中节点 p 和 q 的最低公…

聚类性能度量

在机器学习中&#xff0c;聚类是一种无监督学习&#xff0c;那对于聚类结果&#xff0c;我们应该如何评估其好坏呢&#xff1f;我们这里介绍两类性能度量。 1.外部指标 外部指标的意思是将聚类结果与某个“参考模型”进行比较。哎其实也很好理解&#xff0c;就相当于老师批改卷…

AGI时代引领未来,大模型重塑市场发展

前言 在数字化浪潮席卷全球的今天&#xff0c;人工智能&#xff08;AI&#xff09;技术正以前所未有的速度推动着各行各业的变革。其中&#xff0c;大模型作为AI领域的重要分支&#xff0c;正以其独特的优势&#xff0c;为程序员和企业产品经理这两大核心群体开辟出崭新的发展…

# RocketMQ 实战:模拟电商网站场景综合案例(十)

RocketMQ 实战&#xff1a;模拟电商网站场景综合案例&#xff08;十&#xff09; 一、RocketMQ 实战&#xff1a;模拟电商网站场景综合案例-- 创建支付订单流程 1、支付订单流程 2、在 shop-pay-service 工程模块中&#xff0c;创建 启动 类 PayServiceApplication.java /***…

MT7981B+MT7976C+MT7531A RF定频测试方法

1、从下面网址下载QA软件包&#xff0c;然后在WIN系统下安装QA环境。 https://download.csdn.net/download/zhouwu_linux/89428691?spm1001.2014.3001.5501 在WINDOWS 7系统下先安装WinPcap_4_1_3.exe。 2、搭建硬件环境&#xff0c;电脑先连接仪器&#xff0c;主板网络与电…

天地图开发实战:Vue结合OpenLayers实现动态点位地图

在Web开发中&#xff0c;地图功能是一个常见的需求&#xff0c;尤其是在需要展示地理位置信息的应用程序中。OpenLayers&#xff08;简称OL&#xff09;是一个强大的JavaScript库&#xff0c;用于创建交互式地图。本文将介绍如何利用OpenLayers和天地图API&#xff0c;实现一个…

Mybatis save、saveOrUpdate、update的区别

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 1. save方法 Mybatis的save方法用于插入一条新的记录。当数据库中不存在相同的记录时&#xff0c;会执行插入操作&#xff1b;如果已经存在相同的记录&#xff0c;则会抛出异常。 int result sqlSession.insert(&…

电脑桌面提醒做事的app 好用的桌面提醒app

在快节奏的现代生活中&#xff0c;我们每天都要通过电脑处理大量的工作事项。然而&#xff0c;繁忙的工作节奏有时会导致我们遗忘某些重要任务&#xff0c;从而带来不必要的损失。为了避免这种情况&#xff0c;选择一款好用的桌面提醒app显得尤为重要。 想象一下&#xff0c;你…

Java中Transactional在不同方法间的穿透性,rollbackFor参数含义

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 在Java开发中&#xff0c;经常会遇到需要在一个事务中执行多个操作的场景。为了确保这些操作的原子性&#xff0c;可以使用Spring框架提供的Transactional注解来实现事务管理。然而&#xff0c;在实际开发过程中&…

CVE-2012-2122-mysql未授权访问漏洞复现-vulhub

1.原理 参考&#xff1a;CVE-2012-2122 Mysql身份认证漏洞及利用-CSDN博客 简单来说&#xff0c;除了配置上的问题以外&#xff0c;是密码的验证出现了漏洞&#xff0c;导致尝试次数多了之后直接可以登入 使用&#xff1a;kalivulhub 2.复现 开一下镜像&#xff0c;用的是v…

代码随想录算法训练营第五十八天 | 392.判断子序列

392.判断子序列 题目链接&#xff1a;代码随想录 视频讲解&#xff1a;动态规划&#xff0c;用相似思路解决复杂问题 | LeetCode&#xff1a;392.判断子序列_哔哩哔哩_bilibili 解题思路 本题和求最长公共子序列是一样的&#xff0c;值就是s字符串的长度&#xff0c;如果一致…

拥抱开源,构建未来:王嘉树与 TDengine 的开源之旅

在当代的技术浪潮中&#xff0c;开源文化不仅催生了无数创新技术&#xff0c;也为广大技术爱好者提供了一个展示才华、相互学习的平台。我们今天采访到的这位北京邮电大学电子工程学院的研究生&#xff0c;就是在这样的背景下&#xff0c;通过开源活动不断探索、学习并实现自我…

C++中extern “C“的用法

目的 extern "C"是经常用到的东西&#xff0c;面试题目也经常出现&#xff0c;然则&#xff0c;实际用时&#xff0c;还是经常遗忘&#xff0c;因此&#xff0c;深入的了解一下&#xff0c;以增强记忆。 extern "C"指令非常有用&#xff0c;因为C和C的近亲…