C++中stack和queue的模拟实现

news2024/10/2 16:55:17

目录

1.容器适配器  

1.1什么是适配器      

1.2STL标准库中stack和queue的底层结构

1.3deque的简单介绍

1.3.1deque的原理介绍 

1.3.2deque的优点和缺陷

1.3.3deque和vector进行排序的性能对比

1.4为什么选择deque作为stack和queue的底层默认容器

2.stack的介绍和模拟实现

2.1stack的介绍

2.2stack的模拟实现 

2.2.1传统栈的结构

2.2.2利用vector作为stack的底层容器 

 2.2.3模板中加一个容器类型参数,实现不同容器作为stack的底层容器

3.queue的介绍和模拟实现 

3.1queue的介绍

3.2queue的模拟实现 

3.2.1传统队列的结构

3.2.2利用list作为queue的底层容器 

3.2.3模板中加一个容器类型参数,实现不同容器作为queue的底层容器 


1.容器适配器  

1.1什么是适配器      

        适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另一个接口。

        如上图,需要将两个插口的插头转换为插座能使用的三个插口的插头,就需要一个适配器进行转换,适配器也可以叫做转换器。

1.2STL标准库中stack和queue的底层结构

        虽然stack和queue中也可以存放元素,但是STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这里因为stack和queue只是对其他容器的接口进行了包装,所以stack和queue相当于上述三个抽口的插头,底层容器相当于两个插口的插头,用户需要一个stack或queue的结构,就调用其他的底层容器来弄出一个stack或queue,比如:

1.3deque的简单介绍

1.3.1deque的原理介绍 

        deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两段进行插入和删除操作(普通队列只能在一段插入另一端删除),且时间复杂度为O(1).与vector相比,头插效率高,不需要挪动元素;与list相比,空间利用率高。

        deque并不是真正连续的空间,而是由一段段小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示: 

        双端队列底层是一段假想的连续空间,实际是分段连续的,为了维护其"整体连续"以及随机访问的假想,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示: 

        如上图,deque的存储空间放在一个中控器(可以理解为内存中开辟的一块用于存储deque里面数据的空间)里面,里面的每一方框就是一个缓冲器(这里的缓冲区相当于二维数组的每一行)。上述表明deque的迭代器中有4个东西:(1)node:表示指向的是哪一个缓冲区(相当于表面指向二维数组里面的哪一行)。(2)cur:表面在这个缓冲区的位置。(3)first和last:记录该缓冲区的起始位置和结束位置。具体怎么进行维护的这里就不过多的进行介绍了。

1.3.2deque的优点和缺陷

(1)优点:与vector相比,deque的优势是:头部的插入和删除时,不需要挪动元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此在头部进行插入和删除效率比vector高。与list相比,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

(2)缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某一小空间的边界,导致效率低下,而序列场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,而目前能看到的一个应用就是STL中作为stack和queue的底层数据结构。

1.3.3deque和vector进行排序的性能对比

        这里在vs2022的Release下对vector和deque进行排序的性能比较,第一个是分别在各自容器中进行排序之后时间消耗的比较,第二个是将deque中的数据copy到vector进行排序后返回到deque中与deque中自己排序的时间消耗进行比较。

#include <iostream>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;

void test_op1()
{
	srand(time(0));
	const int N = 1000000;

	deque<int> dq;
	vector<int> v;

	for (int i = 0; i < N; i++)
	{
		auto e = rand() + i;
		v.push_back(e);
		dq.push_back(e);
	}

	int begin1 = clock();
	sort(v.begin(), v.end());
	int end1 = clock();

	int begin2 = clock();
	sort(dq.begin(), dq.end());
	int end2 = clock();

	cout << "vector: " << end1 - begin1 << endl;
	cout << "deque:  " << end2 - begin2 << endl;
}

void test_op2()
{
	srand(time(0));
	const int N = 1000000;

	deque<int> dq1;
	deque<int> dq2;

	for (int i = 0; i < N; ++i)
	{
		auto e = rand() + i;
		dq1.push_back(e);
		dq2.push_back(e);
	}

	int begin1 = clock();
	sort(dq1.begin(), dq1.end());
	int end1 = clock();

	int begin2 = clock();
	// 拷贝到vector
	vector<int> v(dq2.begin(), dq2.end());
	sort(v.begin(), v.end());
	dq2.assign(v.begin(), v.end());
	int end2 = clock();

	printf("deque sort:%d\n", end1 - begin1);
	printf("deque copy vector sort, copy back deque:%d\n", end2 - begin2);
}

int main()
{
	test_op1();
	test_op2();
	return 0;
}

1.4为什么选择deque作为stack和queue的底层默认容器

        stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

        (1)stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或两段进行操作。

        (2)在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。

2.stack的介绍和模拟实现

2.1stack的介绍

2.2stack的模拟实现 

2.2.1传统栈的结构

template <class T>
class Stack
{
private:
	T* _a;    //用数组存储元素
	size_t _top;
	size_t _capacity;
};

2.2.2利用vector作为stack的底层容器 

        这里在stack类里面有一个vector的对象,所有的stack接口通过调用vector的接口进行实现。

namespace XiaoC
{
	template<class T>
	class stack
	{
	public:
		//会调用vector的构造函数进行构造
		stack()
		{}

		void push(const T& x)
		{
			_c.push_back(x);	//调用vector的push_back接口
		}

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

		//取栈顶元素
		T& top() const
		{
			return _c.back();
		}

		size_t size() const
		{
			return _c.size();
		}

		bool empty() const
		{
			return _c.empty();
		}
	private:
		std::vector<T> _c;
	};
}

 2.2.3模板中加一个容器类型参数,实现不同容器作为stack的底层容器

        这里默认给的容器是deque,对于stack来说只要支持push_back()和pop_back()线性结构容器就能用来当作底层容器。

#pragma once
#include <deque>
namespace XiaoC
{
	template <class T, class Container = deque<T>>
	class stack
	{
	public:
		void push(const T& x)
		{
			//用尾部作为栈顶
			_con.push_back(x);
		}

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

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

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

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

	private:
		Container _con;
	};
}

3.queue的介绍和模拟实现 

3.1queue的介绍

3.2queue的模拟实现 

3.2.1传统队列的结构

// 链式结构:表示队列中每个节点的结构
typedef struct QListNode
{ 
    struct QListNode* _pNext; 
    QDataType _data; 
}QNode;
 
// 队列的结构,用两个指针来维护一个队列
typedef struct Queue
{ 
    QNode* _front; 
    QNode* _rear; 
}Queue;

3.2.2利用list作为queue的底层容器 

         这里queue里面有一个list对象,所有queue的接口通过调用list的接口进行实现。

#pragma once
#include <deque>

namespace XiaoC
{
	template<class T>
	class queue
	{
	public:
		queue()
		{}

		void empty()
		{
			return _c.empty();
		}

		void size()
		{
			return _c.size();
		}

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

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

		T& front()
		{
			return _c.front();
		}

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

		T& back()
		{
			return _c.back();
		}

		const T& back() const
		{
			return _c.back();
		}
	private:
		std::list<T> _c;
	};
}

3.2.3模板中加一个容器类型参数,实现不同容器作为queue的底层容器 

        这里默认给的容器是deque,对于queue来说只要支持push_back()和pop_front()线性结构容器就能用来当作底层容器。

namespace XiaoC
{
	template <class T, class Container = deque<T>>
	class queue
	{
	public:
		void push(const T& x)
		{
			//用尾部作为栈顶
			_con.push_back(x);
		}

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

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

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

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

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

	private:
		Container _con;
	};
}

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

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

相关文章

c++-类和对象-点和圆关系

注意&#xff1a; 1.在一个类中可以让另一个类作为成员 2.可以把一个类拆成过个头文件&#xff0c;在.cpp中写成员函数实现&#xff0c;在头文件中留下类的声明和属性 实践 结果

我谈陷波滤波器

《数字图像处理&#xff08;电子信息前沿技术丛书&#xff09;》PP180~182勘误。 陷波滤波器在信号处理中就是带阻滤波器&#xff0c;信号处理中陷波滤波器不是这样定义的&#xff0c;二维比一维有这样的特殊性&#xff0c;我想这是Gonzalez创造的概念&#xff0c;在学术中借用…

初识算法 · 双指针(2)

目录 前言&#xff1a; 盛最多水的容器 题目解析&#xff1a; 算法原理&#xff1a; 算法编写&#xff1a; 有效三角形的个数 题目解析&#xff1a; 算法原理&#xff1a; 算法编写&#xff1a; 前言&#xff1a; 本文介绍两个题目&#xff0c;盛最多水的容器和有效三…

Excel下拉菜单制作及选项修改

Excel下拉菜单 1、下拉菜单制作2、下拉菜单修改 下拉框&#xff08;选项菜单&#xff09;是十分常见的功能。Excel支持下拉框制作&#xff0c;通过预设选项进行菜单选择&#xff0c;可以避免手动输入错误和重复工作&#xff0c;提升数据输入的准确性和效率 1、下拉菜单制作 步…

留存率的定义与SQL实现

1.什么是留存率 留存率是指在特定时间段内&#xff0c;仍然继续使用某项产品或服务的用户占用户总数的百分比。 通常&#xff0c;留存率会以日&#xff0c;周&#xff0c;或月为单位进行统计和分析。 2.SQL留存率常见问题 1.计算新用户登录的日期的次日留存率以及3日留存率 …

【鸿蒙学习】深入了解UIAbility组件

文章目录 组件概述生命周期启动模式基本用法 在鸿蒙操作系统&#xff08;HarmonyOS&#xff09;的开发过程中&#xff0c;UIAbility组件是构建应用界面的关键。本文将带您了解UIAbility组件的概述、生命周期、启动模式以及基本用法&#xff0c;并通过代码示例帮助您更好地掌握这…

微信互助学习平台|互助学习平台系统|基于java的微信互助学习平台设计与实现(源码+数据库+文档)

微信互助学习平台 目录 基于java的微信互助学习平台设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师…

论文阅读- On the Feasibility of Fully AI-automated Vishing Attacks

https://arxiv.org/pdf/2409.13793 目录 摘要 INTRODUCTION II. GOALS AND THREAT MODEL III. VIKING A. Architecture B. Interaction with the LLM C. Audio processing D. Call processing E. Implementation IV. EVALUATION METHODOLOGY A. Experiment design …

NeRF三维重建—神经辐射场

NeRF—神经辐射场 本文介绍了三维重建相关技术&#xff0c;特别是神经辐射场(NeRF)的进步&#xff0c;它通过深度学习实现逼真的三维场景重建。NeRF在计算机图形学、自动驾驶和元宇宙等领域展现出广阔的应用前景&#xff0c;通过改进传统方法&#xff0c;提供更高质量的渲染和沉…

聊聊国内首台重大技术装备(1)

9.9日&#xff0c;工信部发布了《首台&#xff08;套&#xff09;重大技术装备推广应用指导目录&#xff08;2024年版&#xff09;》&#xff0c;在集成电路领域&#xff0c;公布了如下首台机台设备&#xff0c;这确实是一个十分振奋人心的消息&#xff0c;说明我国在半导体制造…

LSTM模型实现光伏发电功率的预测

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

构造函数继承

构造函数继承 主要通过在子类的构造函数中调用父类的构造函数&#xff0c;绑定子类实例的 this&#xff0c;从而实现子类对父类属性的继承。这种方法避免了父类和子类共享原型链上的属性&#xff0c;并且可以传递参数给父类的构造函数。 构造函数继承的实现步骤&#xff1a; …

Windows远程Kylin系统-VNC

Windows远程Kylin系统-VNC 一. 配置 yum源 二. 清理yum缓存 三. 安装VNC并配置 nkvers yum install tigervnc tigervnc-server -ycp /lib/systemd/system/vncserver.service /etc/systemd/system/vncserver:1.service 说明&#xff1a;vncserver:1.service中的&#xff1a;1表…

Windows 环境下安装 Anaconda 并适配到 PowerShell 的保姆级教程

Anaconda Anaconda 是一个流行的 Python 数据科学和机器学习平台&#xff0c;它包括了 Conda 包管理器、Python 以及数百个用于科学计算的库和工具。Anaconda 旨在简化包和环境管理&#xff0c;使得安装、更新和管理软件包变得容易&#xff0c;同时也能够轻松创建和切换不同的P…

案例-百度热榜页面实现

文章目录 效果展示要求内容注意代码内容 效果展示 要求内容 整个盒子大小&#xff1a;536*536标题字体柜20px、加粗&#xff0c;纯黑&#xff0c;换一换字体大小20px、颜色0055db、刷新图标是本地图片内容字体18px、上下边距15px、下边框实心2px颜色f3f3f3这个需要根据页面显示…

【顺序查找】

目录 一. 顺序查找的概念二. 查找的性能计算 \quad 一. 顺序查找的概念 \quad \quad 二. 查找的性能计算 \quad

【LLM论文日更】| 通过指令调整进行零样本稠密检索的无监督文本表示学习

论文&#xff1a;https://arxiv.org/pdf/2409.16497代码&#xff1a;暂未开源机构&#xff1a;Amazon AGI、宾夕法尼亚州立大学领域&#xff1a;Dense Retrieval发表&#xff1a;Accepted at DCAI24 workshopCIKM2024 研究背景 研究问题&#xff1a;这篇文章要解决的问题是如…

Linux学习笔记(三):文件管理、复杂操作与实用工具详解

Linux学习笔记&#xff08;三&#xff09;&#xff1a;文件管理、复杂操作与实用工具详解 Linux 学习笔记&#xff08;二&#xff09;&#xff1a;深入理解用户管理、运行级别与命令行操作 1.文件操作的基本操作 1.1 创建 创建目录 mkdir&#xff1a;创建目录 mkdir /home/d…

【MySQL】多表联合查询常见练习题

数据库表如下&#xff1a; teacher&#xff1a;老师表 course&#xff1a;课程表 student&#xff1a;学生表 class&#xff1a;班级表 sc&#xff1a;成绩表 一、根据上面5张表写sql语句 1. 查询” 01 “课程比” 02 “课程成绩高的学生的信息及课程分数 select student.…

AI智能时代的图书馆未来,你想象过吗!

AI智能时代的图书馆未来&#xff0c;你想象过吗&#xff01; 前言AI智能时代的图书馆未来 前言 教育数字化和 AI 时代的浪潮正汹涌而来&#xff0c;图书馆也站在了变革的十字路口。我们看到高等教育正在发生深刻的变革&#xff0c;从教学模式到人才培养理念&#xff0c;都在经…