C++栈、队列、优先级队列模拟+仿函数

news2024/10/3 0:34:43

 

目录

一、栈的模拟和deque容器

1.deque

1.1deque结构

1.2deque优缺点

2.stack模拟

二、队列的模拟

三、priority_queue优先级队列

1.优先级队列模拟

2.添加仿函数


一、栈的模拟和deque容器

在之前,我们学过了C语言版本的栈,可以看这篇文章 栈和队列。

但是C语言没有模板,我们只能固定一个类型去写,在C++中引入了模板的概念,我们只需要写一份,在调用中给到类型,编译器会自动去帮我们推导是栈里面元素的类型,会非常方便。

1.deque

我们可以看到,库函数里面的栈调用的是一个deque容器。

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

1.1deque结构

首先deque有一个中控数组,这个数据是指针数组,存放的内容是指针,每个指针都指向的一块空间的起始地址。

他的迭代器有  cur(当前数据当前位置)  fisrt(数据起始位置)last(数据结尾位置) node(指向数据的指针)。

头插就去找到最前面的那个有效指针进行头插,尾插就找最后面那个有效指针尾插,遍历就通过迭代器每一个空间块从头遍历到位,就换下一个空间块。

 

1.2deque优缺点

deque实际上是一个缝合怪,他结合了vector和list的内容,将他们糅合在了一起。

优点

与vector比较,deque的优势是 :头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

 但是他也有缺点

deque容器不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list。

那么为何他能在栈和队列中使用,并成为默认容器呢?

因为栈和队列需要尾插,尾删,队列需要尾插,头删deque容器完全可以适配这些需求,因为不需要遍历,并且deque扩容时不需要挪动数据,这也是的deque的效率变高。

2.stack模拟

stack的模拟非常简单,调用模板Container容器的函数就可以了,也不需要迭代器(不用遍历),也不需要构造函数析构函数什么的,因为Container容器是自定义类型,会自动调用的相关构造析构拷贝函数。

#pragma once
#include<deque>
namespace kky
{
	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()
		{
			return _con.back();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

二、队列的模拟

队列模拟跟stack差不都,多了一个back接口,出数据的时候要调用pop_front()

#pragma once
#include<deque>
namespace kky
{
	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()
		{
			return _con.front();
		}
		const T& back()
		{
			return _con.back();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

三、priority_queue优先级队列

优先级队列出数据的时候,会先出优先级高的数据。

如何来判断优先级的高低呢?

这跟你传的数据类型有关,先举个例子

我们插入了   1,10,8,5,6   但出数据的时候缺省按照数据的大小顺序来出的,在这里使用数据的大小来看段他们优先级的高低。

优先级队列出数据时会帮我们做好排序,他的本质就是堆,通过堆的向上向下调整来处理优先级问题。具体堆排序的过程可以看选择排序中的堆排序。

1.优先级队列模拟

优先级队列的模拟实现就是要建堆,每一次插入数据都要进行向上调整,保证是大堆或者小堆。

出数据的时候将第一个数据和最后一个数据互换,再进行尾删,因为第一个数据是我们想要出的数据,将他和最后一个数据交换再尾删,就可以提取出这个数据了,同时现在只有第一个元素不符合小堆或者大堆的情况,其他元素都符合,因此进行一次从索引为0位置的向下调整即可。

namespace kky
{
	template<class T,class Container = vector<T>>
	class priority_queue
	{
	public:
		void adjust_up(size_t child)
		{
			while(child>0)
			{
				size_t parent = (child - 1) / 2;
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					child = parent;
				}
				else
				{
					break;
				}
			}
		}

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

		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size()-1);
		}
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}
		T& top()
		{
			return _con[0];
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

刚刚的代码构建了一个大堆,但是我们如果想要构建小堆,难不成又要重写一份代码吗?  那必定不是可能的。 

2.添加仿函数

在C语言中,我们可以通过函数指针来处理顺序的问题,但是函数指针类型很繁琐,并且不容易理解,C++推出了仿函数来帮助我们处理这类问题。

写一个类,仅仅重载了operator(),返回类型为bool,在后面进行判断的时候,我们就可以调用这个类对象的(),类似于函数一样,就可以处理了,

template<class T>
class Less
{
public:
	bool operator()(const T& x1, const T& x2)
	{
		return x1 < x2;
	}
};

第一个方式太丑陋了,一般使用第二种方式去调用。

那之前,我们代码中的判断语句,都可以通过调用仿函数更改了 

给模板参数再添加一个类

template<class T, class Container = vector<T>,class Compare = Less<T>>

现在就可以开始更改了 

只需要注意顺序即可,需要这样判断的都可以更改,参考如下代码

namespace kky
{
	template<class T, class Container = vector<T>,class Compare = Less<T>>
	class priority_queue
	{
	public:
		void adjust_up(size_t child)
		{
			Compare com;
			while (child > 0)
			{
				size_t parent = (child - 1) / 2;
				if (com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
				}
				else
				{
					break;
				}
			}
		}

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

		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjust_down(0);
		}
		T& top()
		{
			return _con[0];
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

 这是我们写的Less仿函数,如果你想让优先级队列建小堆,就可以写再写一个仿函数

template<class T>
class Greater
{
public:
	bool operator()(const T& x1, const T& x2)
	{
		return x1 > x2;
	}
};

需要的时候调用一下即可 

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

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

相关文章

Qt私有信号实现(private signal)

在使用Qt信号槽机制的时候&#xff0c;有时候我们需要一个信号只能由类内发出&#xff0c;而不允许使用该类对象的用户发出&#xff0c;此时就需要私有信号的支持&#xff0c;而信号的关键字 signals&#xff0c;点进去它的实现&#xff0c;大概如下&#xff1a; signals:再次…

推荐-25个开源软件

今天&#xff0c;我想让您对下一个 25 个出色的开源软件。您可以安装它&#xff0c;并且几乎开箱即用&#xff01; ⚠️使用软件前请检查是否安全️️ 1. Portmaster (Go) — 隐私保护者 Portmaster 由 Safing 开发&#xff0c;是一款开源软件&#xff0c;可帮助您保护在线活…

PyTorch基础(18)-- torch.stack()方法

一、方法详解 首先&#xff0c;看一下stack的直观解释&#xff0c;动词可以简单理解为&#xff1a;把……放成一堆、把……放成一摞。 有了对stack方法的直观感受&#xff0c;接下来&#xff0c;我们正式解析torch.stack方法。 PyTorch torch.stack() method joins (concaten…

cookie过大导致request 400 错误研究

问&#xff1a;get请求太长报400的错误&#xff0c;如何解决&#xff1f;生成系统中经常偶现此问题 问&#xff1a;get请求URL的长度是谁限制的&#xff1f; 问&#xff1a;每一个cookie的value的大小还是同域下cookie的个数做的限制&#xff1f; 现象&#xff1a;出现 400 Ba…

【Android知识笔记】插件化专题(一)

占位式插件化方案 宿主启动插件 Activity 的流程 实现思路: 创建一个 DexClassLoader 类加载其用于加载插件包apk中的 Activity 类 反射调用 AssetManager 的 addAssetPath() 将插件包的路径添加,然后通过该AssetManager的实例构造Resource的实例用以加载插件中的布局 启动…

一个信号间相互干扰问题的发现及解决方法

问题描述&#xff1a;MAX3232串口通讯芯片的输出引脚上存在干扰电平&#xff0c;通过示波器可以看到干扰电平&#xff0c;PC端的串口程序表现为接收到乱码。如下图&#xff0c;环回测试中发了一串字符数据ATCIPSEND后&#xff0c;除了收到环回的ATCIPSEND字符外&#xff0c;还有…

【vue2高德地图api】高德地图forEach批量添加marker点标记,点击获取item对象『全网最详细』【翻遍csdn总结】

系列文章目录 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、展示地图二、getList获取列表数据三、写入marker标记在页面中1、marker的官方文档2、setMarks方法3 点击事件4 学习心得 总结 前…

Qtcreator 编译C++代码并打包成APK

1&#xff1a;首先需要下载正确的SDK&#xff0c;NDK工具 我们可以使用sdkmanager工具来进行确认&#xff0c;我们当前已经安装了哪些模块 2&#xff1a;撰写自己的CMakeLists.txt 或者 QtCreator可以识别的.pro 文件 使用QtCreator 可以生产默认的.pro 文件&#xff0c;其中的…

ChatGPT 助力英文论文翻译和润色

文章目录 一、前言二、主要内容1. 中英互译2. 中文润色3. 英文润色 三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 随着全球化的推进&#xff0c;跨文化交流变得越来越重要。在学术领域&#xff0c;英文论文的质量对于研究成果的传…

Chapter1:C++概述

此专栏为移动机器人知识体系的 C {\rm C} C基础&#xff0c;基于《深入浅出 C {\rm C} C》(马晓锐)的笔记&#xff0c; g i t e e {\rm gitee} gitee链接: 移动机器人知识体系. 1.C概述 1.1 C概述 计算机系统分为硬件系统和软件系统。 硬件系统&#xff1a;指组成计算机的电子…

C++:二叉搜索树的原理和模拟实现

文章目录 二叉搜索树二叉搜索树的基本实现原理 二叉搜索树的实现非递归版本的实现递归版本的实现 二叉搜索树 二叉搜索树也叫做二叉排序树&#xff0c;可以是空树&#xff0c;也可以是满足一些要求的二叉树 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点…

关于C2447 “{”: 缺少函数标题(是否是老式的形式表?)

以下两幅图&#xff0c;实际上并没有任何错误。 OR 我从vscode上把代码移植过来&#xff0c;实际并无任何错误。但是因为这个注释&#xff0c;一直在报错&#xff0c;我把所有注释都删了&#xff0c;程序就自然运行了。所以问题出在哪呢&#xff1f;希望大佬解答。

统信UOS技术开放日:四大领域全面接入AI大模型能力

1024是程序员的节日&#xff0c;10月24日&#xff0c;统信举办2023统信UOS技术开放日暨deepin Meetup北京站活动&#xff0c;发布与大模型同行的UOS AI、浏览器AI助手、邮箱AI助手、自然语言全局搜索、畅写在线等多项最新AI技术与产品应用。 统信软件高级副总经理、CTO、深度社…

C语言知识回顾

链接&#xff1a;https://pan.baidu.com/s/1CiB1Ydm4LTV6hZE8wx0VFw?pwdna4z 提取码&#xff1a;na4z --来自百度网盘超级会员V6的分享

【分布式技术专题】「分布式技术架构」MySQL数据同步到Elasticsearch之N种方案解析,实现高效数据同步

MySQL数据同步到Elasticsearch之N种方案解析&#xff0c;实现高效数据同步 前提介绍MySQL和ElasticSearch的同步双写优点缺点针对于缺点补充优化方案 MySQL和ElasticSearch的异步双写优点缺点 定时延时写入ElasticSearch数据库机制优点缺点 开源和成熟的数据迁移工具选型Logsta…

arcgis js api FeatureLayer加载时返回数据带*问题

接着这一问题衍生出来的问题 arcgis的MapServer服务查询出来的结果geometry坐标点带*的问题-CSDN博客 个人感觉像是server版本的问题&#xff0c;具体不清楚&#xff0c;pg数据库里面的shape点集合坐标点的精度是8&#xff0c;但是server服务查出来的默认都十几位。所以存在一…

使用达梦数据库的总结

–修改当前会话所在模式&#xff1a; set schema 模式名;–创建表空间、用户名并为用户指定表空间&#xff0c;并为用户授权 create tablespace "RSGL_BZK" datafile REGL_BZK.DBF size 7488 autoextend on next 128 maxsize 33554431 CACHE NORMAL; create user …

制作macOS Ventura U盘启动盘教程

macOS 14更新一段时间了&#xff0c;发现某些应用不适配想要无损降级&#xff0c;如何进行macOS的降级呢&#xff0c;除了备份好的时间机器备份&#xff0c;还需要一个可以引导的macOS U盘安装器&#xff0c;如何制作macOS 13 Ventura 系统启动U盘呢&#xff0c;小编带来对新手…

webGL编程指南 第四章 旋转+平移.TanslatedRotatdTriangle

我会持续更新关于wegl的编程指南中的代码。 当前的代码不会使用书中的缩写&#xff0c;每一步都是会展开写。希望能给后来学习的一些帮助 git代码地址 &#xff1a;git 本篇文章将把旋转和平位移结合起来&#xff0c;因为矩阵的不存在交换法则 文章中设计的矩阵地址在这里​…

苹果cms模板MXone V10.6魔改版网站源码短视大气海报样式

安装模板教程说明&#xff1a; 1、将模板压缩包上传到苹果cms程序/template下解压 2、网站板选择mxone 模板目录填写html 3、网站模板选择好之后一定要先访问前台&#xff0c;然后再进入后台设置 4、主题后台地址&#xff1a; 苹果cms后台点击&#xff0c;自定义菜单配置 …