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

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

                     今日主菜: 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.mfbz.cn/a/489964.html

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

相关文章

【Web应用技术基础】HTML(5)——案例1:展示简历信息

样式&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>展示简历信息…

【微服务】Gateway

文章目录 1.基本介绍官方文档&#xff1a;https://springdoc.cn/spring-cloud-gateway/#gateway-starter1.引出网关2.使用网关服务架构图3.Gateway网络拓扑图&#xff08;背下来&#xff09;4.Gateway特性5.Gateway核心组件1.基本介绍2.断言3.过滤 6.Gateway工作机制 2.搭建Gat…

从姿态估计到3D动画

在本文中&#xff0c;我们将尝试通过跟踪 2D 视频中的动作来渲染人物的 3D 动画。 在 3D 图形中制作人物动画需要大量的运动跟踪器来跟踪人物的动作&#xff0c;并且还需要时间手动制作每个肢体的动画。 我们的目标是提供一种节省时间的方法来完成同样的任务。 我们对这个问题…

超实用!10条JavaScript这20年来增加的新功能?

部门捞人&#xff1a;前端可投&#xff1a;OD软件工程师社会招聘-表单-金数据 在过去的20年里&#xff0c;JavaScript经历了多次更新和升级&#xff0c;引入了许多新功能以增强其表达力、交互性和开发效率。以下是一些显著的新功能&#xff1a; 1.ECMAScript 6 (ES6) &#xf…

【ssh连接】奇奇怪怪报错记录

gitlab配置ssh连接&#xff0c;先跟着教程生成密钥&#xff0c;上传公钥&#xff0c;将服务器信息存入config文件&#xff0c;但是ssh连接超时&#xff0c;很急&#xff0c;想用服务器&#xff0c;各种搜索尝试&#xff0c;搞了两三天别的什么都没干&#xff0c;还是没解决&…

vue脚手架创建项目:账号登录(利用element-ui快速开发)(取消eslint强制格式)(修改端口号)

新手看不懂&#xff0c;老手不用看系列 文章目录 一、准备工作1.1 取消强制格式检查1.2 导入依赖&#xff0c;注册依赖 二、去element-ui官网找样式写Login组件2.1 引用局部组件2.2 运行项目 三、看一下发现没问题&#xff0c;开始修改前端的代码四、修改端口号4.1 修改后端端口…

中国赛道领跑之争:安踏将耐克越甩越远

一双鞋、一件衣服每被穿一次&#xff0c;消费者就会把它背后的品牌和自身的体验联系起来&#xff0c;做出评判。所以&#xff0c;如果说有什么领域能充分展示国产品牌的发展进步&#xff0c;鞋服一定包含在内&#xff0c;尤其是强调专业性的体育运动市场。 一年前的2023年3月&…

CSS3语法及选择器总结

CSS定义 css是一种样式表语言&#xff0c;用来美化HTML文档 一.CSS的引用 方式一:内部样式表(HTML中引用) 在HTML的title标签下方添加style双标签&#xff0c;style标签里面书写CSS *style里面的注释为/ * … / CSS的书写规则: 选择器{属性名&#xff1a;属性值&#xff…

Vue+Element-UI el-table表格根据指定条件动态合并行span-method

当涉及到展示复杂数据的表格时&#xff0c;Element UI 中的 el-table 是一个非常有用的组件。在某些情况下&#xff0c;可能需要对表格进行合并显示以提高可读性。 案例需求&#xff1a;页面中有个表格组件&#xff0c;其中包含了一些学生的姓名、年级、负责班级和科目成绩等信…

20240319-2-机器学习基础面试题

⽼板给了你⼀个关于癌症检测的数据集&#xff0c;你构建了⼆分类器然后计算了准确率为 98%&#xff0c; 你是否对这个模型很满意&#xff1f;为什么&#xff1f;如果还不算理想&#xff0c;接下来该怎么做&#xff1f; 首先模型主要是找出患有癌症的患者&#xff0c;模型关注的…

水离子雾化壁炉的设计特点与优势

水离子雾化壁炉具有许多独特的设计特点和优势&#xff0c;使其在家居装饰和氛围营造方面具有吸引力。以下是其主要设计特点和优势&#xff1a; 仿真火焰效果&#xff1a; 水离子雾化壁炉采用超声波雾化技术将水分子雾化成微细的水离子&#xff0c;然后通过风扇吹出再经过UVC紫…

Binary Search Tree

这篇博客要说的是二叉搜索树&#xff0c;又叫二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;那么左子树上所有节点的值都小于根节点的值&#xff0c;不会出现等于的情况 若它的右子树不为空&#…

树状数组(概念 + 模板 + 例题)

1 . 概念 修改 &#xff0c; 就是从前往后修 &#xff0c; 查寻&#xff0c;就是从后往前查&#xff0c;然后累加 ; 2 . 模板 : #define lowbit(x) (x&(-x)) // 获取最后一个1 const int N 5e510;int n , m , s[N] ; // 向后修 void change(int x , int k){while(x&l…

全自动引流,每日500+粉丝的秘诀

在如今竞争激烈的市场环境下&#xff0c;如何有效地吸引和保持精准粉丝成为了每个企业主或网红必须面对的问题。然而&#xff0c;许多人可能误以为全自动引流就意味着无人参与&#xff0c;实际上&#xff0c;它更多的是借助一些自动化工具和策略来提升我们的工作效率。今天&…

代码随想录 图论

目录 797.所有可能得路径 200.岛屿数量 695.岛屿的最大面积 1020.飞地的数量 130.被围绕的区域 417.太平洋大西洋水流问题 827.最大人工岛 127.单词接龙 841.钥匙和房间 463.岛屿的周长 797.所有可能得路径 797. 所有可能的路径 中等 给你一个有 n 个节点的…

java项目通用Dockerfile

创建Dockerfile文件&#xff0c;放到项目根目录下和pom.xml同级别 仅需修改为自己项目端口号即可&#xff0c;其他的无需改动 FROM openjdk:11.0.11-jre-slimCOPY target/*.jar .EXPOSE 8080ENTRYPOINT java -jar *.jar构建语句(注意末尾的点 . ) docker build -t container…

GIS+Python:地质灾害风险评价的智能化解决方案

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…

后端常见面经之MySQL

MySQL字段类型 数值类型 整型经常被用到&#xff0c;比如 tinyint、int、bigint 。默认是有符号的&#xff0c;若只需存储无符号值&#xff0c;可增加 unsigned 属性。 int(M)中的 M 代表最大显示宽度&#xff0c;并不是说 int(1) 就不能存储数值10了&#xff0c;不管设定了显…

17:00面试,17:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

如何用二维码分享视频?视频转二维码在电脑生成的方法

现在很多的视频都会通过生成二维码的方式来完成分享&#xff0c;在手机上通过扫码预览内容更符合现在人群的行为习惯&#xff0c;从而提升用户获取内容的效率及用户体验。而且这种方式的应用对于制作者而言也可以通过更快的方法来完成视频分享&#xff0c;有效的降低自身需要花…