[STL]priority_queue类及反向迭代器的模拟实现

news2024/11/13 10:16:27

 🪐🪐🪐欢迎来到程序员餐厅💫💫💫

                     今日主菜: priority_queue类及反向迭代器

                                            主厨:邪王真眼

  主厨的主页:Chef‘s blog  

 所属专栏:c++大冒险

        

 向着c++,塔塔开!


[本节目标]

  • 1.仿函数

  • 2.priority_queue

  • 3.反向迭代器

一.仿函数

1.1仿函数是什么

仿函数(Functor)是一种重载了函数调用运算符(operator())的类对象,他的使用方法看起来与函数极其相似,却又有不同,因此成为仿函数

1.2仿函数的定义与使用

我们现在写一个可以比较两个变量大小的仿函数以及函数

template<class T>
class Less
{
	bool operator()(const T&a,const T&b )
	{
		return a < b;
	}
};
template<class T>
	bool  Less(const T& a, const T& b )
	{
		return a < b;
	}

那么问题来了,仿函数的优势是什么呢?

我们知道有时候为了在函数中调用别的函数我们需要传一个叫做函数指针的东西,简单的函数还好,复杂的函数的指针是真的难看懂,于是乎,仿函数横空出世,你要用它就传个他的类就行,一下子容易多了。

二、priority_queue

2.1 priority_queue的介绍

1. 优先队列是一种容器适配器,STL中默认使用的容器是vector(不过deque也可以)
2. 他存储数据的结构是堆,默认是大堆。
3.  底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:
  1. empty():检测容器是否为空
  2. size():返回容器中有效元素个数
  3. front():返回容器中第一个元素的引用
  4. push_back():在容器尾部插入元素
  5. pop_back():删除容器尾部元素
4.  需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、 push_heap pop_heap 来自动完成此操作。

2.2成员变量

	template<class T, class Container = vector<T>, class Compare = Less<T>>
	class priority_queue
	{
	public:
		//函数
	private:
		Container _con;
	};
我们是直接模拟的STL的格式,但事实上,在模板参数那里,应该把Container放到最后才合适,因为我们一般不会修改使用的容器,但会选择建一个大堆或者小堆,STL的格式导致我们在调整为小堆时,必须也写容器才行(盲猜大佬写的时候喝假酒了)。

2.3empty

判断容器适配器是否为空
	bool empty()
	{
		reutrn _con.empty();
	}

2.4size

返回容器适配器的元素个数

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

2.5top

返回堆顶元素

注意事项:我们的返回值是const类型,没有非const,这是因为如果你用非const就可能导致堆顶元素修改,进而导致结构不再是大堆或小堆。

	constT& top()const
	{
		_con.front();
	}

2.6push

入堆

  • 1.先尾插
  • 2.在向上调整
		void push(T& val)
		{
			_con.push_back(val);
			UpAdjust();
		}
		void UpAdjust(size_t number)//大堆
		{
			int child = number - 1;
			int parent = child = (child-1) / 2;
			while (child)
			{
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child-1) / 2;
				}
				else
					break;

			}
		}

这里我们既要思考,如果建一个小堆那就要在写一个函数,可是他们两个函数只有

这里需要改变,一个是>,一个是<。

于是乎,我们立刻想到了再加一个模板参数,用它来处理这个大于小于的问题,

如下:

template<class T>
class Less
{
	bool operator()(const T&a,const T&b )
	{
		return a < b;
	}
};
template<class T>
class Greater
{
	bool operator()(const T& a, const T& b)
	{
		return a > b;
	}
};	

void push(T& val)
	{
		_con.push_back(val);
		UpAdjust();
	}
	Compare com;
	void UpAdjust(size_t number)//大堆
	{
		int child = number - 1;
		int parent = child = (child-1) / 2;
		while (child)
		{
			if (com(_con[parent] , _con[child]))
			{
				swap(_con[child], _con[parent]);
				child = parent;
				parent = (child-1) / 2;
			}
			else
				break;

		}
	}

2.7pop

出堆

这个就比较难了,为了保证堆的结构尽可能不被破坏以降低时间复杂度,我们选择:

  1. 先把第一个元素和最后一个元素交换位置
  2. 最后删除最后一个元素。
  3. 在对堆顶进行向下调整法
  4. 构造一个仿函数模板对象,再利用重载的()运算符进行比较
template<class T>
class Less
{
	bool operator()(const T&a,const T&b )
	{
		return a < b;
	}
};
template<class T>
class Greater
{
	bool operator()(const T& a, const T& b)
	{
		return a > b;
	}
};	
		Compare com;
		void DownAdjust(size_t size)
		{
			int parent = 0;
			int child = parent * 2+1;
			while (child<size)
			{
				if (child<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 pop()
	{
		swap(_con[0], _con[size() - 1]);
_con.pop_back();
		DownAdjust(size());
	}

三、反向迭代器

反向迭代器是一种适配器,它是根据不同容器的正向迭代器,来生成对应的反向迭代器。

反向迭代器的rbegin对应迭代器的end位置,rend对应begin位置。

3.1 成员变量

细节:

  1. 使用struct,标明公有属性
  2. 成员变量是一个正向迭代器
template <class Iterator,class Ref,class Ptr>
struct ReverseItreator
{
	typedef ReverseIterator<Iterator, Ref, Ptr> self;
	Iterator it;
};

3.2默认成员函数

写一个缺省的构造,别的编译器自动生即可。

	ReverseItreator(Iterator val=Iterator())
		:it(val)
	{}

3.3operator*

	Ref operator*()
	{
		Iterator its = it;
		its--;
		return *its;
	}

3.4operator--

self operator--()
{
	return ++it;
}
self operator--()const
{
	Iterator its = it;
	++it;
	return its;
}

3.5operator++

	self operator++()
	{
		return --it;
	}
	self operator++()const
	{
		Iterator its = it;
		--it;
		return its;
	}

3.6operator->

	Ptr operator->()
	{
		return  & (*it);
	}

3.7operator==,operator!=

	bool operator==(const self&s)
	{
		return it = s.it;
	}
	bool operator !=(const self& s)
	{
		return it = s.it;
	}

3.8反向迭代器的应用

在容器中,以vector举例

template<class T>
class vector
{
public:
	typedef T* Iterator;
	typedef const T* Const_Iterator;

	typedef ReverseIterator<Iteartor, T&, T*> Reverse_Iterator;
	typedef ReverseIterator<Iteartor, constT&,cosnt T*> Const_Reverse_Iterator;
	Iterator end()
	{
		return _finish;
	}
	Const_Iterator end()const
	{
		return _finish;
	}
	Iterator begin()
	{
		return _start;
	}
	Const_Iterator begin()const
	{
		return _start;
	}

private:
	T* _start;
	T* _finish;
};

反向迭代器函数:

	Reverse_Iterator rbegin()
	{
		return (Reverse_Iterator)end();
	}
	Const_Reverse_Iterator rbegin()const
	{
		return (Const_Reverse_Iterator)end();
	}
	Reverse_Iterator rend()
	{
		return (Reverse_Iterator)begin();
	}
	Const_Reverse_Iterator rend()const
	{
		return (Const_Reverse_Iterator)begin();
	}

这时候我们就要提个问题了,就拿rbegin了,来说吧

看看这个函数怎么样:

	Reverse_Iterator begin()
	{
		return _finish;
	}

乍一看似乎完全没问题,但是但是,如果是list你咋办呢,是deque你咋办呢,他们都没有这个

_finish成员变量啊,所以我们一开始就说了,它是根据不同容器的正向迭代器,来生成对应的反向迭代器。反向迭代器去调用正向迭代器的实现方法才能保证他的普适性

总结

  • 仿函数的用法及优势,并在priority_queue适配器中加以应用
  • 对priority_queue进行了了解和模拟,
  • 实现很久前就提到的了反向迭代器,对迭代器这个概念有了更深的了解。

感觉有用的话就点个赞支持一下吧

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

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

相关文章

特征融合篇 | YOLOv8改进之将主干网络SPPF更换为SimSPPF / SPP-CSPC / SPPF-CSPC

前言:Hello大家好,我是小哥谈。SimSPPF是YOLOv6中提出的一种改进的空间金字塔池化方法,它是SPPF的升级版。SimSPPF通过在不同尺度上使用不同大小的池化核来提取特征,从而提高了检测器的性能。与SPPF相比,SimSPPF可以在不增加计算成本的情况下提高检测器的性能。本节课就教…

【软件设计师】原码反码补码移码

数值1数值-1原码0000000110000001反码0000000111111110补码0000000111111111移码1000000101111111 正数 00000001 负数 10000001 正数&#xff1a;原码、反码、补码一样 负数&#xff1a;反码是原码符号位不变&#xff0c;其他取反&#xff1b;补码是反码1 移码是补码首位取…

八、C#计数排序算法

简介 计数排序是一种非比较性的排序算法&#xff0c;适用于排序一定范围内的整数。它的基本思想是通过统计每个元素的出现次数&#xff0c;然后根据元素的大小依次输出排序结果。 实现原理 首先找出待排序数组中的最大值max和最小值min。 创建一个长度为max-min1的数组count…

Ambari——编译——解决替换yarn 版本后 系mvn 打包找不到yarn 文件问题

您的支持是我继续创作与分享的动力源泉!!! 您的支持是我继续创作与分享的动力源泉!!! 您的支持是我继续创作与分享的动力源泉!!! 报错原因&#xff1a; [ERROR] Failed to execute goal com.github.eirslett:frontend-maven-plugin:1.4:yarn (yarn install) on project amb…

入驻抖音小店后这些设置必须打开! 非常重要!否则小店无法运行!

哈喽~我是电商月月 大家入驻完抖音小店后是不是就不管了&#xff0c;直接去选品&#xff1f; 我现在告诉你&#xff0c;直接选品后你会发现你的抖音小店根本运行不了&#xff01; 为什么&#xff1f;那是因为这些设置你没打开&#xff1a; 一抖音号绑定店铺官方账号 抖音小…

Covalent Network(CQT)的以太坊时光机:在 Rollup 时代确保长期数据可用性

以太坊正在经历一场向 “Rollup 时代” 的转型之旅&#xff0c;这一转型由以太坊改进提案 EIP-4844 推动。这标志着区块链技术的一个关键转折&#xff0c;采用了一种被称为“数据块&#xff08;blobs&#xff09;”的新型数据结构。为了与以太坊的扩容努力保持一致&#xff0c;…

面试笔记——Java集合篇

Java集合框架体系 重点&#xff1a;单列集合——ArrayList、LinkedList&#xff1b;双列集合——HashMap、ConcurrentHashMap。 List相关 数组&#xff08;Array&#xff09; 是一种用连续的内存空间存储相同数据类型数据的线性数据结构。 数组获取其他元素&#xff1a; 为什…

【微服务】接口幂等性常用解决方案

一、前言 在微服务开发中&#xff0c;接口幂等性问题是一个常见却容易被忽视的问题&#xff0c;同时对于微服务架构设计来讲&#xff0c;好的幂等性设计方案可以让程序更好的应对一些高并发场景下的数据一致性问题。 二、幂等性介绍 2.1 什么是幂等性 通常我们说的幂等性&…

leetcode 714

leetcode 714 题目 例子 思路1 使用dp[n][2] 存储最佳利润值&#xff0c;动态规划的思路&#xff0c;重要的是转移方程。 代码1 class Solution { public: int maxProfit(vector& prices, int fee) { int n prices.size(); //dp[i][0] 前i天手里没有股票的最大利润 //…

Share-ChatGPT官网UI/文件上传/联网搜索/GPTS 一并同步

地址&#xff1a;Share-ChatGPT 文章目录 界面UI&#xff0c;GPTS&#xff0c;读论文&#xff0c;数据分析&#xff0c;写论文视频演示仓库地址 界面 支持多账号同时管理&#xff0c;合理利用资源&#xff1a; UI&#xff0c;GPTS&#xff0c;读论文&#xff0c;数据分析&a…

老家稳定月薪3000工作和互联网企业3万怎么选?

这是发生在身上的真事。其实刚回老家心里落差非常的大&#xff0c;老家也不需要信息安全非常专业的人才&#xff0c;最终因为各种综合原因选择了回老家&#xff0c;有父母的因素&#xff0c;有4年2次被优化的因素&#xff0c;有互联网行业35岁的因素等等。 我回老家发展很多人…

C语言(结构体,联合体,枚举的讲解)

这期我们来讲解结构体&#xff0c;联合体&#xff0c;以及枚举的讲解&#xff0c;首先我们从概念开始一步一步的了解。 1&#xff0c;结构体 1.1概念 C 语言中的结构体是一种用户自定义的数据类型&#xff0c;它允许你将不同类型的变量组合在一起&#xff0c;从而形成一个新…

集合(下)Map集合的使用

文章目录 前言一、Map接口二、Map接口的实现类 1.HashMap类2.TreeMap类总结 前言 Map集合没有继承Collection接口&#xff0c;不能像List集合和Set集合那样直接使用Collection接口的方法。Map集合其自身通过以key到value的映射关系实现的集合&#xff0c;也有相应的许多方法。类…

零基础机器学习(3)之机器学习的一般过程

文章目录 一、机器学习一般过程1.数据获取2.特征提取3.数据预处理①去除唯一属性②缺失值处理A. 均值插补法B. 同类均值插补法 ③重复值处理④异常值⑤数据定量化 4.数据标准化①min-max标准化&#xff08;归一化&#xff09;②z-score标准化&#xff08;规范化&#xff09; 5.…

[蓝桥杯 2023 省 A] 颜色平衡树:从零开始理解树上莫队 一颗颜色平衡树引发的惨案

十四是一名生物工程的学生&#xff0c;他已经7年没碰过信息学竞赛了&#xff0c;有一天他走在蓝桥上看见了一颗漂亮的颜色平衡树&#xff1a; [蓝桥杯 2023 省 A] 填空问题 - 洛谷 十四想用暴力解决问题&#xff0c;他想枚举每个节点&#xff0c;每个节点代表一棵树&#xff0…

风险评估在网络安全领域的应用与实践

一、引言 在数字化浪潮席卷全球的今天&#xff0c;网络安全已成为企业运营和发展的核心问题。随着信息技术的快速发展&#xff0c;企业面临着日益复杂的网络安全威胁&#xff0c;如黑客攻击、数据泄露、恶意软件等。这些威胁不仅可能导致企业重要信息的丢失或泄露&#xff0c;…

C++模版(基础)

目录 C泛型编程思想 C模版 模版介绍 模版使用 函数模版 函数模版基础语法 函数模版原理 函数模版实例化 模版参数匹配规则 类模版 类模版基础语法 C泛型编程思想 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。 模板是泛型编程…

Retelling|Facebook2

录音 Facebook 2 Retelling|Facebook2 复述转写 Hi, Im Helen Campbell, from DJ interpretation, European Commission, Im going to talk about Facebook. You Im sure that you are more familiar with Facebook, a lot, a lot more familiar than I than me. But Ive read…

JavaSE系统性总结全集(精华版)

目录 1. 面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;详解 1.1 面向过程和面向对象的区别 1.2面向对象的三大特性 1.2.1 封装 1.2.2 继承 1.2.3 多态 1.2.4 方法重写和方法重载的区别&#xff08;面试题&#xff09; 1.2.5 访问权限修饰符分…

clickhouse学习笔记02(小滴课堂)

ClickHouse核心基础-常见数据类型讲解 插入数据&#xff1a; decimal类型的数据&#xff0c;整数部分超了会报错&#xff0c;小数部分超了会截取。 查看表结构&#xff1a; 查询&#xff1a; 插入&#xff1a; 更新操作&#xff1a; 这个和mysql的语句不太一样。 删除语句和my…