【C++之容器适配器】栈和队列模拟实现

news2024/11/24 5:08:38

目录

    • 前言
    • 一、栈(stack)
      • 1. 基本代码结构
      • 2. 简介
      • 3. 成员类型
      • 4. 成员函数
        • 1. 构造函数
        • 2. empty()
        • 3. size()
        • 4. top()
        • 5. push()
        • 6.pop()
        • 7. 综合测试实现的stack的所有函数接口
    • 二、队列(queue)
      • 1. 基本代码结构
      • 2. 队列的简介
      • 3. 成员类型
      • 4. 成员函数
        • 1. 构造函数
        • 2. empty()
        • 3. size()
        • 4. front()
        • 5. back()
        • 6. push()
        • 7. pop()
        • 8. 综合测试实现的queue的所有函数接口
    • 三、优先级队列(priority_queue)
      • 1. 基本代码结构
      • 2. 简介
      • 3. 成员类型
      • 4. 成员函数
        • 1. 构造函数
        • 2. empty()
        • 3. size()
        • 4. top()
        • 5. push()
        • 6. pop()
        • 7. 综合测试实现的priority_queue的所有函数接口

前言

前面我们学习的都是C++标准模板库中的一些容器,今天我们要学习几个容器适配器,容器适配器的底层原理是通过适配另一个容器的功能来完成当前容器功能的实现,今天学习的栈和队列是通过deque来适配的,下面我们详细讲解stack和queue还有priority_queue的模拟实现

一、栈(stack)

1. 基本代码结构

在这里插入图片描述

2. 简介

在这里插入图片描述

3. 成员类型

在这里插入图片描述

4. 成员函数

1. 构造函数

在这里插入图片描述
栈的底层是使用deque来进行适配的,deque是一个自定义类型的成员,所以栈自身不需要实现默认构造函数,编译器生成的默认构造函数会去调用deque的默认构造函数完成初始化。

2. empty()

在这里插入图片描述

这个函数的功能是判断栈是否为空,如果为空则返回true,如果不为空,则返false。同样的道理,stack的底层是适配了一个deque,所以直接调用deque的empty()完成判断即可。

  • 代码:
		bool empty() const
		{
			return _con.empty();
		}

3. size()

在这里插入图片描述
这个函数的功能是求栈中的元素个数。同样的道理,stack的底层是适配了一个deque,所以直接调用deque的size()完成判断即可。

  • 代码:
		size_t size() const
		{
			return _com.size();
		}

4. top()

在这里插入图片描述
这个函数的功能是求栈的栈顶元素。同样的道理,stack的底层是适配了一个deque,所以直接调用deque的back()完成判断即可。

  • 代码:
		const T& top() const
		{
			return _con.back();
		}

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

5. push()

在这里插入图片描述
这个函数的功能是将元素入栈。同样的道理,stack的底层是适配了一个deque,所以直接调用deque的push_back()完成判断即可。

  • 代码:
		void push(const T& val)
		{
			_con.push_back(val);
		}

6.pop()

在这里插入图片描述
这个函数的功能是将元素出栈。同样的道理,stack的底层是适配了一个deque,所以直接调用deque的pop_back()完成判断即可。

  • 代码:
void pop()
		{
			_con.pop_back();
		}

7. 综合测试实现的stack的所有函数接口

  • 代码:
void test_stack()
{
	hjt::stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);

	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;

}

int main()
{
	test_stack();
	return 0;
}

运行结果:
在这里插入图片描述

二、队列(queue)

1. 基本代码结构

namespace hjt
{
	template <class T,class Container = deque<T>>
	class queue
	{
	public:
		// 成员函数

	private:
		Container _con;
	};
}

2. 队列的简介

在这里插入图片描述

3. 成员类型

在这里插入图片描述

4. 成员函数

1. 构造函数

在这里插入图片描述
队列的底层是使用deque来进行适配的,deque是一个自定义类型的成员,所以队列自身不需要实现默认构造函数,编译器生成的默认构造函数会去调用deque的默认构造函数完成初始化。

2. empty()

在这里插入图片描述

这个函数的功能是判断队列是否为空,如果为空则返回true,如果不为空,则返false。同样的道理,queue的底层是适配了一个deque,所以直接调用deque的empty()完成判断即可。

  • 代码:
		bool empty() const
		{
			return _con.empty();
		}

3. size()

在这里插入图片描述
这个函数的功能是求队列中的元素个数。同样的道理,queue的底层是适配了一个deque,所以直接调用deque的size()完成判断即可。

  • 代码:
		size_t size() const
		{
			return _con.size();
		}

4. front()

在这里插入图片描述
这个函数的功能是求队列的队头元素。同样的道理,queue的底层是适配了一个deque,所以直接调用deque的front()完成判断即可。

  • 代码:
		const T& front() const
		{
			return _con.front();
		}

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

5. back()

在这里插入图片描述

这个函数的功能是求队列的队尾元素。同样的道理,queue的底层是适配了一个deque,所以直接调用deque的back()完成即可。

  • 代码:
		const T& back() const
		{
			return _con.back();
		}

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

6. push()

在这里插入图片描述
这个函数的功能是将元素入队。同样的道理,queue的底层是适配了一个deque,所以直接调用deque的push_back()完成即可。

  • 代码:
		void push(const T& val)
		{
			_con.push_back(val);
		}

7. pop()

在这里插入图片描述
这个函数的功能是将元素出队。同样的道理,queue的底层是适配了一个deque,所以直接调用deque的pop_front()完成即可。

  • 代码:
		void pop()
		{
			_con.pop_front();
		}

8. 综合测试实现的queue的所有函数接口

  • 代码:
void test_queue()
{
	hjt::queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);
	q.push(6);

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

}
  • 运行结果:
    在这里插入图片描述

三、优先级队列(priority_queue)

1. 基本代码结构

// 实现优先级队列
	template <class T,class Container = vector<T>>
	class priority_queue
	{
	public:
		// 成员函数

	private:
		Container _con;
	};

2. 简介

在这里插入图片描述

3. 成员类型

在这里插入图片描述

4. 成员函数

1. 构造函数

在这里插入图片描述
优先级队列的底层是使用vector来进行适配的,vector是一个自定义类型的成员,所以优先级队列自身不需要实现默认构造函数,编译器生成的默认构造函数会去调用vector的默认构造函数完成初始化。

2. empty()

在这里插入图片描述
这个函数的功能是判断优先级队列是否为空,如果为空则返回true,如果不为空,则返false。同样的道理,priority_queue的底层是适配了一个vector,所以直接调用vector的empty()完成判断即可。

  • 代码:
bool empty() const
		{
			return _con.empty();
		}

3. size()

在这里插入图片描述
这个函数的功能是求优先级队列中元素个数,同样的道理,priority_queue的底层是适配了一个vector,所以直接调用vector的empty()完成判断即可。

  • 代码:
	size_t size() const
		{
			return _con.size();
		}

4. top()

在这里插入图片描述
这个函数的功能是求优先级队列中队顶元素,队顶元素是第一个元素,所以返回_con中的第一个元素即可。

  • 代码:
const T& top() const
		{
			return _con[0];
		}

5. push()

在这里插入图片描述
这个函数的功能是将数据插入priority_queue中,并且要保证插入数据之后仍然满足堆的性质,所以还需要实现一个向上调整算法

  • 代码:
void push(const T& val)
		{
			_con.push_back(val);
			AjustUp(_con.size() - 1);
		}

		void AjustUp(int child)
		{
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[parent] < _con[child])
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

6. pop()

在这里插入图片描述
这个函数的功能是删除priority_queue中的队顶元素,并且要保证插入数据之后仍然满足堆的性质,所以还需要实现一个向下调整算法

		void pop()
		{
			assert(!_con.empty());
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AjustDown(0);
		}

		void AjustDown(int parent)
		{
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if(child + 1 < _con.size() && _con[child] < _con[child + 1])
				{
					child++;
				}
				if (_con[parent] < _con[child])
				{
					swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
				
			}
		}

7. 综合测试实现的priority_queue的所有函数接口

  • 代码
void test_priority_queue()
{
	hjt::priority_queue<int> pq;
	pq.push(1);
	pq.push(2);
	pq.push(3);
	pq.push(4);
	pq.push(5);
	pq.push(6);

	cout << "pq:" << endl;
	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

	hjt::priority_queue<int> pq1;
	pq1.push(3);
	pq1.push(1);
	pq1.push(2);
	pq1.push(5);
	pq1.push(6);
	pq1.push(7);
	cout << "pq1:" << endl;
	while (!pq1.empty())
	{
		cout << pq1.top() << " ";
		pq1.pop();
	}
	cout << endl;


}
  • 运行结果:
    在这里插入图片描述

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

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

相关文章

leaflet 上传KML文件,导出geojson文件(065)

第065个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中本地上传kml文件,利用解析此kml文件,在地图上显示图形。点击导出geojson,将下载为geojson文件。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代…

ChatGPT 怎么用最新详细教程-新手小白一看就会

ChatGPT 以其强大的信息整合和对话能力惊艳了全球&#xff0c;在自然语言处理上面表现出了惊人的能力。这么强大的工具我们都想体验一下&#xff0c;那么 ChatGPT 怎么用呢&#xff1f;本文将给你逐步详细介绍。使用 ChatGPT 主要有4步&#xff1a;注册 ChatGPT 账号通过短信接…

vue 开发环境 卸载node 版本 切换新的 node 版本 mac电脑

注意&#xff1a;操作的机器当前是mac&#xff0c;先卸载&#xff0c;再安装 1.查看现有 node 版本 node -v2.卸载现有 node 版本&#xff0c; 1.卸载从node官网下载pkg安装的node sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man/*/node…

地址空间 (Address Space)

文章目录&#xff1a;程序地址空间进程地址空间程序地址空间 什么是地址空间&#xff1a;地址空间是内存中可供程序或进程使用的有效地址的范围。也就是说&#xff0c;它是程序或进程可以访问的内存。内存可以是物理的、也可以是虚拟的&#xff0c;用于执行指令和存储数据。 …

nginx开启Gzip压缩,Vue性能优化之使用gzip压缩打包

一、前言不管是vue项目还是react项目在使用webpack打包之后都会生成一个动辄一两兆甚至更大的js文件&#xff0c;在某些情况下严重影响项目性能&#xff0c;打开页面的时候白屏时间会很长&#xff0c;本文将介绍如何使用gzip压缩打包&#xff0c;主要是nginx部署的配置&#xf…

hadoop环境新手安装教程

1、资源准备&#xff1a; &#xff08;1&#xff09;jdk安装包&#xff1a;我的是1.8.0_202 &#xff08;2&#xff09;hadoop安装包&#xff1a;我的是hadoop-3.3.1 注意这里不要下载成下面这个安装包了&#xff0c;我就一开始下载错了 错误示例&#xff1a; 2、主机网络相…

天荒地老修仙功-第六部:Spring Cloud中7中负载均衡策略

文章目录前言Ribbon介绍负载均衡设置七种负载均衡策略1、轮询策略2、权重策略3、随机策略4、最小链接数策略5、重试策略6、可用性敏感策略7、区域敏感策略总结前言 负载均衡器通常有两种实现手段&#xff0c;一种是服务端负载均衡器&#xff0c;另一种是客户端负载均衡器&…

线程池的常见知识点总结

文章目录1. 什么是线程池2. 为什么使用线程池3. 线程的作用4. 如何创建线程池5. 线程持底层是如何实现复用的6. 手写一个简易的线程池7. ThreadPoolExecutor构造函数原理8. 线程池创建的线程会一直运行下去吗&#xff1f;9. 线程池队列满了任务会丢失吗&#xff1f;分析情况有界…

xilinx srio ip学习笔记之axistream接口

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 xilinx srio ip学习笔记之axistream接口前言接口转化前言 srio 的IQ接口都是基于axistream的&#xff0c;以前没怎么用过axistream的接口&#xff0c;或者说没怎么用过复杂条…

C语言--数据的存储2

目录前言练习有符号类型与无符号类型char类型的取值范围有符号char无符号char有符号与无符号类型混合运算有符号无符号类型形成的bugchar类型取值范围应用浮点型在内存中的存储浮点数的存储浮点数存储规则浮点数取出规则前言 上篇文章我们讲解了数据类型&#xff0c;类型的基本…

招标采购流程的电子招标采购,是管理复杂供应链和多层供应商的高效方式。

负载均衡&#xff08;Load Balance&#xff09; 由于目前现有网络的各个核心部分随着业务量的提高&#xff0c;访问量和数据流量的快速增长&#xff0c;其处理能力和计算强度也相应地增大&#xff0c;使得单一的服务器设备根本无法承担。在此情况下&#xff0c;如果扔掉现有设…

(二)、安装uview及配置项中的易错项【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

1.打开hbuilder软件&#xff0c;新建uniapp项目 2.关联unicloud服务空间 2.1 项目文件夹鼠标右键&#xff0c;打开uicloud web控制台 2.2 注册HBuilder 账号 dcloud账号注册链接 2.3 新建服务空间 大约等待2分钟&#xff0c;服务空间初始化完毕&#xff01;就可以使用了。 …

每天10个前端小知识 【Day 15】

前端面试基础知识题 1.两个同级的相邻元素之间&#xff0c;有看不见的空白间隔&#xff0c;是什么原因引起的&#xff1f;有什么解决办法&#xff1f; 行框的排列会受到中间空白&#xff08;回车空格&#xff09;等的影响&#xff0c;因为空格也属于字符,这些空白也会被应用样…

Mob研究院联合明源地产研究院发布《2022年商业地产发展白皮书》

Mob研究院近日联合明源地产研究院共同发布《2022年商业地产发展白皮书》&#xff0c;报告从行业现状、企业概况、新兴业态和未来展望四个方面对商业地产行业进行了全景扫描&#xff0c;深入分析了由于疫情的影响以及消费人群和习惯的改变&#xff0c;2022年商业地产行业中所发生…

Ubuntu 22.04安装搜狗输入法

Ubuntu 22.04安装搜狗输入法 ubtuntu 22.04安装搜狗输入法 1. 添加中文语言支持2. 安装fcitx输入法框架3. 设置fcitx为系统输入法4. 设置fcitx开机启动&#xff0c;并卸载ibus输入法框架5. 安装搜狗输入法6. 重启电脑&#xff0c;调出搜狗输入法 1. 添加中文语言支持 Setti…

营销自动化的CRM系统能够解决哪些问题

CRM客户管理系统营销自动化的范围远远超出了人们的认知。许多人认为它只是自动化完成重复和乏味的任务来减少营销人员的工作量。虽然这确实占了很大一部分&#xff0c;但它真正的价值在于提高潜客转化&#xff0c;增加业务收入。那么&#xff0c;什么是CRM系统营销自动化&#…

【23种设计模式】行为型模式详细介绍(上)

前言 本文为 【23种设计模式】行为型模式 相关内容介绍&#xff0c;下边将对访问者模式&#xff0c;模板模式&#xff0c;策略模式&#xff0c;状态模式&#xff0c;观察者模式&#xff0c;备忘录模式&#xff0c;中介者模式&#xff0c;迭代器模式&#xff0c;解释器模式&…

实现一个简单的Database10(译文)

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a; 花家舍文章来源&#xff1a;GreatSQL社区原创 前文回顾 实现一个简单的Database系列 译注&#xff1a;csta…

测试用例设计工作中的应用

1. 等价类划分 常见的软件测试面试题划分等价类: 等价类是指某个输入域的子集合.在该子集合中,各个输入数据对于揭露程序中的错误都是等效的.并合理地假定:测试某等价类的代表值就等于对这一类其它值的测试.因此,可以把全部输入数据合理划分为假设干等价类,在每一个等价类中取一…

水溶性花青素连接剂1617497-19-4,diSulfo-Cyanine5 alkyne,二磺酸花青素Cy5炔基

一、理论分析&#xff1a;中文名&#xff1a;二磺酸-花青素Cy5-炔基英文名&#xff1a;diSulfo-Cy5 alkyne&#xff0c;diSulfo-Cyanine5 alkyne&#xff0c;diSulfo Cyanine5 alkyneCAS号&#xff1a;1617497-19-4化学式&#xff1a;C35H40N3NaO7S2分子量&#xff1a;701.8二、…