【C++初阶】:优先队列(仿函数)

news2024/10/7 10:21:46

优先队列

  • 一.基本使用
  • 二.模拟实现
  • 三.仿函数
    • 1.优先队列里的使用
    • 2.概念
    • 3.模拟

一.基本使用

优先队列的底层默认是使用vector构造的,也就是使用数组模拟(二叉树)堆。并且默认是按大堆存放数据(也就是父节点>子节点,左节点>右节点)。

在这里插入图片描述

优先队列的成员函数不多,常用的就是empty,size,top,pop,push。

在这里插入图片描述

简单使用

首先优先队列常使用区间初始化和无参初始化。

在这里插入图片描述

可以使用push插入数据,注意因为优先队列是使用数组模拟堆,所以不能直接遍历。只能通过不断访问顶部数据,再不断弹出顶部数据进行间接遍历。

在这里插入图片描述

在这里插入图片描述

二.模拟实现

这里使用了模板参数(template<class T,class Container=vector>),一共有两个参数,第一个T用来适配不同类型的数据(例如int,string或者自定义类型),第二个参数默认是vector,也就是底层默认是用vector实现优先队列,当然也可以使用list等等(这里与库里保持一致)。

#include<vector>

namespace mine
{
	template<class T,class Container=vector<T>>
	class priority_queue
	{
	private:
		//向下调整
		void AdjustDown(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[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}	
			}
		}

		//向上调整
		void AdjustUp(int child)
		{
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[parent] <_con[child])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
	public:
		//无参构造
		priority_queue()
		{}
		//区间构造
		template<class InputLterater>
		priority_queue(InputLterater first,InputLterater last)
		{
			while (first != last)
			{
				_con.push_back(*first);
				first++;
			}

			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				AdjustDown(i);
			}
		}
		//弹出顶部数据
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}
		//插入数据
		void push(const T&x)
		{
			_con.push_back(x);
			AdjustUp(_con.size() - 1);
		}
		//访问顶部数据
		const T& top()
		{
			return _con[0];
		}
		//数组大小
		size_t size()
		{
			return _con.size();
		}
		//是否为空
		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};

}

测试

#include<iostream>
using namespace std;

#include"priority_queue.h"


int main()
{
	int a[9] = { 4,8,1,9,6,7,2,5,5};
	mine::priority_queue<int> v(a,a+9);//使用区间初始化


	mine::priority_queue<int> vv;//无参初始化
	vv.push(5);
	vv.push(2);
	vv.push(7);
	vv.push(11);
	while (!vv.empty())
	{
		cout << vv.top() << ' ';
		vv.pop();
	}
	return 0;
}

三.仿函数

1.优先队列里的使用

在库里除了T,Container两个模板参数外,还有一个Compare参数,这是一个仿函数用来改变存储顺序(默认是less,也就是大堆,可以改成greater,也就是小堆)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.概念

仿函数的底层实际很简单,就是一个类里面重载了一个括号()运算符。

在这里插入图片描述

在这里插入图片描述

仿函数的本质就是一个类的对象可以像函数一样使用。

3.模拟

由于less,greater本质都是类,库里有实现,所以就可以直接使用。

#include<vector>

namespace mine
{
	template<class T,class Container=vector<T>,class Compare=less<T>>
	class priority_queue
	{
	private:
		//向下调整
		void AdjustDown(int parent)
		{
			Compare com;
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (com(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 AdjustUp(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (com(_con[parent],_con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
	public:
		//无参构造
		priority_queue()
		{}
		//区间构造
		template<class InputLterater>
		priority_queue(InputLterater first,InputLterater last)
		{
			while (first != last)
			{
				_con.push_back(*first);
				first++;
			}

			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				AdjustDown(i);
			}
		}
		//弹出顶部数据
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}
		//插入数据
		void push(const T&x)
		{
			_con.push_back(x);
			AdjustUp(_con.size() - 1);
		}
		//访问顶部数据
		const T& top()
		{
			return _con[0];
		}
		//数组大小
		size_t size()
		{
			return _con.size();
		}
		//是否为空
		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};

}

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

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

相关文章

51单片机串口

该部分的笔记来自视频教程链接https://www.bilibili.com/video/BV1bt4y197NR/?spm_id_from333.788&vd_sourceb91967c499b23106586d7aa35af46413 一、51单片机串口基础介绍 一般的应用层的协议中采用和校验或CRC校验&#xff0c;而奇偶校验还是解决基本通信中的帧格式中的…

练习时长两年半的网络安全防御“second”

目录 1.防火墙的安全区域 Trust区域 DMZ区域 Untrust区域 Local区域 安全区域的受信任程度与优先级 2. 安全策略 ​编辑 安全域间、安全策略与报文流动方向 安全域间是用来描述流量的传输通道&#xff0c;它是两个“区域”之间的唯一“道路”。如果希望对经过这条通 …

C++初阶 - 4.类和对象(下)

目录 1.再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 ---- 是构造函数的一部分 1.3 explicit 关键字 2.static成员 2.1概念 2.2 特性 3.友元 3.1友元函数 3.2 友元类 4.内部类 5.再次理解类和对象 1.再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0…

Hadoop中HDFS的架构

一、Switch语句 语法规则&#xff1a; ①语句中的变量类型可以是byte、short、int或者char;从javaSE5开始支持枚举类型&#xff1b; javaSE7开始&#xff0c;switch支持String。 ②没有break时&#xff0c;后续case的语句都会执行 二、修饰符 访问修饰符 Java中&#xff0c…

机器人导航(2):导航实现

文章目录 SLAM建图gmapping简介gmapping节点说明gmapping使用 地图服务map_server简介map_server使用之地图保存节点(map_saver)map_server使用之地图服务(map_server)map_server节点说明地图读取地图显示 定位amcl简介amcl节点说明订阅的Topic发布的Topic服务调用的服务参数坐…

prometheus直方图实践

目录 1.简介 2.方案 1.简介 Prometheus提供了Counter、Gauge、Histogram、Summary四类指标&#xff08;详见Metric types | Prometheus&#xff09;&#xff0c;可以通过"github.com/prometheus/client_golang/prometheus"自定义采集指标、注册、采集数据、发布UR…

gerrit 提交搞了一天的账号密码

搞了一整天的账号密码怎么输入都不对 以为输入了也不对&#xff0c;查找各种文档也不太行 参考也不太行&#xff1a; https://blog.csdn.net/qq_43279637/article/details/103595122 最后发现 是使用了git clone http 脑残方式&#xff0c;正确应该使用 git clone ssh 就可以…

XILINX ZYNQ 7000 AXI总线 (三) AXI GPIO

一步一步来搭建一下AXI GPIO 创建ZYNQ 后先来看下各个接口的含义 1.M_AXI_GP0_ACKL和M_AXI_GP0 ZYNQ的PS部分是有一个GP接口&#xff0c;32 Bit 的AXI master接口&#xff0c;默认是打开的&#xff0c;如果双击绿框可以看到是打开的 M_AXI_GP0 就是AXI的主机接口&#xff…

电脑C盘空间大小调整 --- 扩容(扩大/缩小)--磁盘分区大小调整/移动

概述&#xff1a; 此方法适合C盘右边没有可分配空间&#xff08;空闲空间&#xff09;的情况&#xff0c;D盘有数据不方便删除D盘分区的情况下&#xff0c;可以使用傲梅分区助手软件进行跨分区调整分区大小&#xff0c;不会损坏数据。反之可直接使用系统的磁盘管理工具进行调整…

HTTPS连接过程中的中间人攻击

HTTPS连接过程中的中间人攻击 HTTPS连接过程中间人劫持攻击 HTTPS连接过程 https协议就是httpssl/tls协议&#xff0c;如下图所示为其连接过程&#xff1a; HTTPS连接的整个工程如下&#xff1a; https请求&#xff1a;客户端向服务端发送https请求&#xff1b;生成公钥和私…

Android Hook 剪切板相关方法

想起之前做过的项目有安全合规要求&#xff1a;主动弹窗获取用户同意了才能调用剪切板相关方法&#xff0c;否则属于违规调用&#xff0c;如果是自己项目的相关调用可以自己加一层if判断 但是一些第三方的jar包里面也有在调用的话&#xff0c;我们就无能为力了&#xff0c;而且…

云原生容器内的一次pg_repack排错和解决过程

postgresql的pg_repack 这个cronjob一直执行不了。 排错过程: 用命令 kubectl describe job pg-repack-scheduler-manual-wv82r -n xxx没有查看用有用信息想办法进它启动的pod查看&#xff0c;于是在执行pg_repack.sh命令前&#xff0c;先加一个睡眠时间&#xff0c;如下: - …

Megatron-LM:Transformer模型专用分布式张量模型并行方法

论文标题&#xff1a;Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism 论文链接&#xff1a;https://arxiv.org/abs/1909.08053 论文来源&#xff1a;NVIDIA 一、概述 随着自然语言处理领域预训练语言模型的规模变得越来越大&#xff…

access跨库查询

服务器上面安装了安全狗、Waf这样的安全软件&#xff0c;没有办法下载数据库内容 都在同一个服务器的不同网站&#xff0c;从11查12的数据库 12数据库路径在C:\wwwtest\2AspCMS\AspCms_data 把data.asp后缀改成mdb就能看到里面的表了&#xff0c;data.mdb如下 语句 当前网站…

CSS自学框架之表格和项目列表

表格和项目列表很直观的显示数据&#xff0c;是我们web开发中经常遇到的最简单表现信息形式。具体代码如下&#xff1a; 一、css代码 ul,ol{margin-left: 1.25em;} /* - 表格 */.myth-table{width: 100%;overflow-x: auto;overflow-y: hidden;border-radius: var(--radius);…

《Pytorch深度学习和图神经网络(卷 2)》学习笔记——第二章

基于图片内容的处理任务 主要包括目标检测、图片分割两大任务。 目标检测&#xff1a;精度相对较高&#xff0c;主要是以检测框的方式&#xff0c;找出图片中目标物体所在坐标。模型运算量相对较小&#xff0c;相对较快。 图片分割&#xff1a;精度相对较低&#xff0c;主要是…

【工具-jmeter】jmeter 入门级 demo 练习

目录 前言&#xff1a; 1. Jmeter 准备 1.1 jmeter 安装包下载 1.2 jmeter 启动 1.3 jmeter 语言选择 2. Jmeter 运行 1 个 Web 请求的 demo 2.1 添加 1 个 Thread Group 线程组 2.2 添加 1 个 HTTP Request 请求 2.3 乱码问题 2.4 添加 1 个 HTTP Header 请求头 2.…

开发中遇到的 cookie 问题

1. cookie 无法跨域携带问题 尽管已经登录&#xff0c;但是请求接口返回状态码&#xff1a;202&#xff0c;msg&#xff1a; 未登录&#xff0c;如下图所示&#xff1b; 1.1 XMLHttpRequest.withCredentials未设置 如果需要跨域 AJAX 请求发送 Cookie&#xff0c;需要withCre…

【UE】虚幻网络同步

UE网络官方文档链接&#xff1a;https://docs.unrealengine.com/5.2/zh-CN/networking-overview-for-unreal-engine/ 虚幻的网络模式 服务器作为游戏主机&#xff0c;保留一个真实授权的游戏状态。换句话说&#xff0c;服务器是多人游戏实际发生的地方。客户端会远程控制其在服…