C++9:优先级队列以及仿函数和反向迭代器

news2024/9/23 5:33:12

目录

 优先级队列的基本增删查改实现

仿函数

反向迭代器


 优先级队列的本质其实是一个堆,具体到底层的数据结构其实是有数学关系所形成的一个类似二叉树的结构

至于其优先级的这个特性,跟大堆小堆的性质是相同的,只不过它使用了仿函数来控制生成大堆还是小堆。

 优先级队列的基本增删查改实现

 具体的实现以及逻辑都是堆的,没啥可以记述的,想不起来点这里

数据结构6:二叉树与堆_数据结构堆和二叉树_lanload的博客-CSDN博客

 底层是一个vector非常合理,写起来也没有C语言那么蛋疼,但是由于本身vector对越界行文会进行报错,所以说逻辑还是需要处理好,调整求取父节点下标的时候很有可能越界,比如向下调整的时候,whil循环里头的chil是否大于0需要先行被检测,不然就报错了

#pragma once
#include <iostream>
#include<vector>
using namespace std;
template<class T, class Container = vector<T>>
class Mypriority_queue
{
	// 优先级队列的本质是一个堆。而堆的本质则是有数学关系所形成的一个二叉树
	//       0
	//    1     2
	// 3    4 5    6
	//一个子节点的-1/2将会得到父节点的下标,同理,父节点*2+1得到左孩子,*2+2得到右孩子
	//

public:
	//构造函数
	Mypriority_queue()
	{}
	//迭代器构造函数
	template<class iterator>
	Mypriority_queue(iterator begin, iterator end)
	{
		while (begin != end)
		{
			push_back(*begin);
			++begin;
		}
	}

	void Adjustdown(size_t parent)
	{
		size_t minchild = parent * 2 + 1;

		while (minchild <_a.size())
		{
			if (minchild + 1 < _a.size() && _a[minchild] >_a[minchild + 1])
			{
				++minchild;
			}

			if (_a[parent] > _a[minchild])
			{
				std::swap(_a[parent], _a[minchild]);
				parent = minchild;
				minchild = parent * 2 + 1;
			}
			else
			{
				break;
			}
		}
	}





	//向上调整,每次插入就向上调整一次
	//传递一个当前插入位置的下标,那么先求出其父节点的下标,默认建一个小堆。
	void Adjustup(size_t child)
	{
		size_t parent = (child - 1) / 2;


		while (child > 0 && _a[parent] > _a[child]  )
		{
			std::swap(_a[parent], _a[child]);
			child = parent;
			parent=(child - 1) / 2;
		}
	}
	//void Adjustup(size_t child)
	//{
	//	size_t parent = (child - 1) / 2;
	//	while (child > 0)
	//	{
	//		if (_a[parent] < _a[child])
	//		{
	//			std::swap(_a[child], _a[parent]);
	//			child = parent;
	//			parent = (child - 1) / 2;
	//		}
	//		else
	//		{
	//			break;
	//		}
	//	}
	//}


	void push_back(const T& val)
	{
		_a.push_back(val);


		Adjustup(_a.size() - 1);
	}
	
	void pop()
	{
		std::swap(_a[0], _a[_a.size() - 1]);
		_a.pop_back();

		Adjustdown(0);
	}


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

	//T& operater[](size_t pos) 
	//{
	//	return _a[pos];
	//}
	const T& top() const
	{
		return _a[0];
	}


private:
	Container _a;

};

仿函数

 仿函数是对某一个类中的()运算符进行重载,其运作原理类似于函数的一个类。

如下:

	template<class T>
	class less
	{
		bool operator()(const T& x,const T& y)
		{
			return x < y;
		}
	};

用起来就像函数调用

int main()
{
	text::less<int> Less;

	Less(1, 2);
}

等价于

Less.operator()(x,y);
  • 其主要的特征就是,仿函数的对象使用起来与函数的方法一致,虽然其并不是函数,而是一个对象。
  • 但这么但看还是蛮鸡肋的,我单独写一个函数再套一个函数模板不是更方便吗?为什么要用仿函数这个玩意?写起来还麻烦
  • 以当前的优先级队列举例,我们在实现的时候会遇到不得不写死逻辑的情况,发生于向上调整以及向下调整的过程中建立的是大堆还是小堆的问题。
	void Adjustup(size_t child)
	{
		size_t parent = (child - 1) / 2;


		while (child > 0 && _a[parent] > _a[child]  )
		{
			std::swap(_a[parent], _a[child]);
			child = parent;
			parent=(child - 1) / 2;
		}
	}
  • 那么在C语言的阶段,如果我们希望解决这个问题,可以额外的写两个函数来解决这个问题,一个比较小于的布尔值,另一个返回大于的布尔值。但是这也引申出非常尴尬的问题,C语言只能传递我们平常见都不想见的函数指针,可读性差不说,还难以掌控。
  • 那么我们刚才实现的仿函数就可以直接使用了,具体用法如下。
  • 我们先把两个仿函数的类创建出来,一个返回小于,另一个返回大于的比较情况

template<class T>
class Less
{
	bool operator()(T& x, T& y)
	{
		return x < y;
	}
};


template<class T>
class Greater
{
	bool operator()(T& x, T& y)
	{
		return x > y;
	}
};

由于传递的是一个类对象,我们在优先级队列的模板参数列表处新增一个模板参数,称之为Compare,缺省值给一个小于,也就是默认生成小堆。

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

 然后更改一下调整函数内部的比较逻辑。

具体代码就不完全罗列了,已上传至仓库。模拟实现优先级队列 · Lanload/C++学习代码记录 - Gitee.com

小堆

 大堆,注意的是,大堆的适配器类型需要显示声明,不然会报错,因为这个时候和缺省值的语法冲突,要么全部使用缺省值,要么全部显示调用,本人犯了这个错误,记录一下。

 仿函数还有一系列及其有用的其他用法,官方库内部实现的less以及greater不能比较指针,这是我们也可以自己写一个。

综上所述,仿函数的出现为我们使用类和对象的时候提供了一个逻辑模板,通过与模板结合我们可以成功的借助仿函数控制逻辑。

目前的仿函数也只是吃了个甜品,之后还会有更加复杂的使用。


反向迭代器

 反向迭代器的实现模式等同于适配器设计模式,传入一个正向迭代器,适配出反向迭代器。

那么这样的结构有点像list的迭代器,那么我们简单实现一个

由于STL源码中涉及的萃取过于复杂,我们统一模板参数,以获取到模板参数T,也就是当前对象数据类型。

#pragma once
//反向迭代器,通过传入一个正向迭代器适配出一个反向版本
//不涉及萃取,获取T类型就用简单粗暴的方式
template<class Iterator,class Ref,class Ptr>
class Reverse_iterator
{
public:
	Reverse_iterator(Iterator it)
		:_it(it)
	{}

	typedef Reverse_iterator<Iterator,Ref,Ptr> Self;


	//++变--
	Self& operator++()
	{
		--_it;
		return *this;
	}

	Self& operator--()
	{
		++_it;
		return *this;
	}

	//解引用,保持堆成时需要特殊处理一下,返回当前迭代器指向数据的引用
	Ref operator *()
	{
		Iterator tmp = _it;
		return *--tmp;
	}


	//p->等价于(*p).内部变量
	Ptr operator->()
	{
		return &(operator*());
	}

	bool operator!= (const Self& s) const
	{
		return _it != s._it;
	}


private:
	Iterator _it;
};

其中的解引用操作之所以--是为了同源码实现以下对齐,源码中传递的参数是对齐传递的。

假若没有--,那么数据的访问将会是一个随机值然后访问不到rend处。

反向迭代器仅做了解,不过多记述了。

 反正没人看,当笔记做,摆

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

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

相关文章

bool与引用类型

bool与引用类型bool类型介绍与使用bool(布尔类型)大小&#xff1a;1个字节返回值有两个&#xff1a;1(true)&#xff0c;0(false)#include<iostream>using namespace std;int main() {bool a false;bool b true;cout << "a " << a << end…

Lighthouse组合Puppeteer检测页面

如上一篇文章lighthouse的介绍和基本使用方法结尾提到的一样&#xff0c;我们在实际使用Lighthouse检测页面性能时&#xff0c;通常需要一定的业务前置条件&#xff0c;比如最常见的登录操作、如果没有登录态就没有办法访问其他页面。再比如有一些页面是需要进行一系列的操作&a…

从编年史角度看大数据兴起

开源大数据编年史大数据发展的各阶段大数据诞生初期大数据百花齐放的发展之路追求性能的大数据成熟期大数据发展的各阶段 开源大数据的编年史的话&#xff0c;实际上分为三个阶段。一般来说它分为初期、发展期、成熟期。 初期就是大数据刚开始萌芽的一个阶段&#xff0c;它从…

java 8 中的实用技巧

1 判断2个对象是否相等Objects.equals(a, b)(1) 比较时&#xff0c; 若a 和 b 都是null, 则返回 true, 如果a 和 b 其中一个是null, 另一个不是null, 则返回false。注意&#xff1a;不会抛出空指针异常。(2) a 和 b 如果都是空值字符串&#xff1a;"", 则 a.equals(b…

深入浅出解析ChatGPT引领的科技浪潮【AI行研商业价值分析】

Rocky Ding写在前面 【AI行研&商业价值分析】栏目专注于分享AI行业中最新热点/风口的思考与判断。也欢迎大家提出宝贵的意见或优化ideas&#xff0c;一起交流学习&#x1f4aa; 大家好&#xff0c;我是Rocky。 2022年底&#xff0c;ChatGPT横空出世&#xff0c;火爆全网&a…

CXL互联标准简介及相关资料

毕设是实现CXL的type3扩展内存设备&#xff0c;因为CXL技术非常新&#xff0c;2019年推出&#xff0c;本专栏也是记录CXL的相关知识与一些浅薄的理解 文章目录CXL出现的背景CXL是什么其他互联总线介绍CXL胜出的原因CXL内容简介包含三种协议 CXL.io/cache/memory支持三种设备类型…

SQL注入原理及漏洞利用(入门级)

文章目录一、什么是SQL注入漏洞&#xff1f;二、 SQL查询语句三、SQL注入分类数字型&#xff08;整型&#xff09;注入字符型注入搜索型注入四、SQL注入漏洞形成原因一、什么是SQL注入漏洞&#xff1f; 攻击者利用Web应用程序对用户输入验证上的疏忽&#xff0c;在输入的数据中…

基于Istio的高级流量管理二(Envoy流量劫持、Istio架构、高级流量管理)

文章目录一、Envoy流量劫持机制&#xff08;Iptables规则流转&#xff09;1、流量出向劫持流程&#xff08;1&#xff09;envoy怎样劫持入向流量&#xff1f;&#xff08;2&#xff09;Envoy劫持到流量之后&#xff0c;干什么&#xff1f;&#xff08;查询目的地&#xff09;&a…

tess4j简单使用入门

tess4j下载 下载地址: https://sourceforge.net/projects/tess4j/ 不要直接下载,点击files,然后下载最新版 下载解压后放到指定的目录即可,这里放到d:\jar目录下 tess4j根目录: d:\jar\tess4j tess4j使用 把test4j项目目录中dist和lib目录下的所有jar包导入到需要的项目中…

【云原生】k8s 离线部署讲解和实战操作

文章目录一、概述二、前期准备1&#xff09;节点信息2&#xff09;修改主机名和配置hosts3&#xff09;配置ssh互信4&#xff09;时间同步5&#xff09;关闭防火墙6&#xff09;关闭 swap7&#xff09;禁用SELinux8&#xff09;允许 iptables 检查桥接流量三、开始部署1&#x…

【OC】块初识

Block简介 Blocks是C语言的扩充功能。可以用一句话来表示Blocks的扩充功能&#xff1a;带有自动变量的匿名函数。 匿名函数 所谓匿名函数就是不带有名称的函数。C语言的标准不允许存在这样的函数。例&#xff1a; int func(int count);它声明了名称为func的函数。下面的源代…

STM32 ROS控制器底层代码讲解

本文主要对控制器底层代码的整天架构进行讲解。控制器由两部分组成一部分是BootLoader,另一部分是APP&#xff1b;BootLoader主要用于固件升级&#xff0c;APP则作为应用程序。BootLoader的地址为:0x8000000~0x8008000App的地址为:0x8010000~0x8FFFFFF参数保存地址为&#xff1…

基本密码技术

AESAES取代DES&#xff0c;是一种对称加密技术&#xff0c;分为AES-128/192/256, 其分组长度固定为128b&#xff0c;若最后一个分组长度不够&#xff0c;需要补全至128b长度。所支持的秘钥长度分别为128b/192b/256b.分组密码模式AES是对明文进行分组之后逐块进行加密&#xff0…

2023年软考高级网络规划设计师

网络规划设计师是软考高级考试科目之一&#xff0c;也是比较难的科目&#xff0c;据官方数据统计网规每年的通过率很低&#xff0c;而且每年只有下半年11月份考一次&#xff0c;如果是直接裸考&#xff0c;估计很悬哦~ 但是你参加考试获得证书的过程就是一个学习网络规划系统知…

【python学习笔记】:SQL常用脚本(一)

1、行转列的用法PIVOT CREATE table test (id int,name nvarchar(20),quarter int,number int) insert into test values(1,N苹果,1,1000) insert into test values(1,N苹果,2,2000) insert into test values(1,N苹果,3,4000) insert into test values(1,N苹果,4,5000) insert…

本周大新闻|索尼PS VR2立项近7年;传腾讯将引进Quest 2

本周大新闻&#xff0c;AR方面&#xff0c;传立讯精密开发苹果初代AR头显&#xff0c;第二代低成本版将交给富士康&#xff1b;iOS 16.4代码曝光新的“计算设备”&#xff1b;EM3推出AR眼镜Stellar Pro&#xff1b;努比亚将在MWC2023推首款AR眼镜。VR方面&#xff0c;传闻腾讯引…

编辑器、论坛、评论列表图文混排的一些思路

好久没写帖子了&#xff0c;今天写一个吧 众所众知从用户那里拿到的数据直接innerHtml插入 有被xss攻击的风险&#xff0c;所以一般会转义,拿csdn编辑文章的来举个例子 通过前端转义 ‘>’后,传给后台&#xff1b;这里title没有用innerHtml而是文本所以不需要转义。 前端请…

SerenityOS 操作系统类 Unix 操作系统

创建于2018年的SerenityOS是一个类似Unix的操作系统&#xff0c;但是带有图形化界面&#xff0c;适合X86台式计算机&#xff0c;&#xff0c;其界面类似90 年代的Win98/NT。几乎由一个人完成额操作系统。这几天其Web浏览器通过了 Acid3 浏览器。 Kernel features 具有抢占式多…

计算机网络笔记、面试八股(四)—— TCP连接

本章目录4. TCP连接4.1 TCP报文段的首部格式4.2 TCP连接如何保证可靠4.3 ARQ协议4.3.1 停止等待ARQ协议4.3.1.1 无差错情况4.3.1.2 出现差错情况4.3.1.3 确认丢失和确认迟到4.3.2 连续ARQ协议4.3.2.1 流水线传输4.3.2.2 累积确认4.3.2.3 滑动窗口协议4.3.3 停止等待ARQ和连续AR…

java面试题-JVM内存结构

整体结构&#xff1a;1.说说JVM内存整体的结构&#xff1f;线程私有还是共享的&#xff1f;JVM&#xff08;Java Virtual Machine&#xff09;内存可以分为以下几个部分&#xff1a;程序计数器&#xff08;Program Counter Register&#xff09;&#xff1a;是线程私有的&#…