c++初阶-----适配器---priority_queue

news2024/9/21 10:58:05

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


priority_queue

  • **作者前言**
  • 介绍
    • 使用
    • 模拟
      • 普通模拟
      • 类似C语言的回调函数方法
      • **仿函数**
        • 小总结

介绍

翻译:

  1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
  2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元
    素)。
  3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特
    定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。
  4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭
    代器访问,并支持以下操作:
    empty():检测容器是否为空
    size():返回容器中有效元素个数
    front():返回容器中第一个元素的引用
    push_back():在容器尾部插入元素
    函数声明 接口说明
    priority_queue()/priority_queue(first,0last) 构造一个空的优先级队列
    empty( )
    检测优先级队列是否为空,是返回true,否则返回
    false
    top( ) 返回优先级队列中最大(最小元素),即堆顶元素
    push(x) 在优先级队列中插入元素x
    pop() 删除优先级队列中最大(最小)元素,即堆顶元素
    pop_back():删除容器尾部元素
  5. 标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指
    定容器类,则使用vector。
  6. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数
    make_heap、push_heap和pop_heap来自动完成此操作。

使用

#include<iostream>
#include<queue>
using namespace std;
typedef priority_queue<int> i;
int main()
{
	i qt;
	qt.push(4);
	qt.push(5);
	qt.push(6);
	qt.push(9);
	qt.push(1);
	while (!qt.empty())
	{
		cout << qt.top() << endl;
		qt.pop();
	}


	return 0;
}

结果:
在这里插入图片描述
如果要想priority_queue是从小到大可以使用greater 类型

#include<iostream>
#include<vector>
#include<queue>
#include<functional>
using namespace std;
typedef priority_queue<int, vector<int>, greater<int>> i;
int main()
{
	i qt;
	qt.push(4);
	qt.push(5);
	qt.push(6);
	qt.push(9);
	qt.push(1);
	while (!qt.empty())
	{
		cout << qt.top() << endl;
		qt.pop();
	}


	return 0;
}

在这里插入图片描述

模拟

priority_queue的底层是,所以,我们模拟的时候,可以理解为是堆的插入和删除
在这里插入图片描述
可以看出 这个容器有三个类型, T 、 vector 、 less

普通模拟

template<class T, class contaier = vector<T> >
class my_priorty_queue
{
public:
	void push(const T& num)
	{
		//尾插
		a.push_back(num);
		//建堆,向上调整
		upajust();


	}
	void pop()
	{
		//首尾交换
		swap(a[0], a[a.size() - 1]);
		//删除尾部
		a.pop_back();
		//向下调整
		downadjust();
	}
	void upajust()
	{
		this->a;
		//向上调整,建大堆
		int i = (this->a).size() - 1;
		while (i > 0)
		{
			if (a[i] > a[(i - 1) / 2])
			{
				swap(a[i], a[(i - 1) / 2]);
				i = (i - 1) / 2;
			}
			else
				break;
		}
	}
	void downadjust()
	{
		int father = 0;
		
		while (father < a.size())
		{
			//进行分类,如果没有孩子,只有一个孩子,两个孩子
			if (a.size()-1< 2 * father + 1)
				break;
			else if (a.size() - 1 < 2 * father + 2)
			{
				if (a[father] < a[2 * father + 1])
				{
					swap(a[father], a[2 * father + 1]);
				}
				else
					break;
			}
			else
			{
				int leftchila = 2 * father + 1;
				int rightchila = leftchila + 1;
				int pos = 0;
				if (a[leftchila] < a[rightchila])
				{
					pos = rightchila;
				}
				else
				{
					pos = leftchila;
					
				}
					
				if (a[pos] > a[father])
					swap(a[pos], a[father]);
				else
					break;
				father = pos;
			}
		}

			//孩子比较出最小的

	}
	bool empty()
	{
		return a.empty();
	}
	T top()
	{
		assert(a.size());
		return a[0];
	}
private:
	contaier a;

};

这样写只能手动改代码进行建立大小堆,不太好用,
我们有两个方法进行控制其中的大小堆,
一个是C语言的的回调函数,一个是c++的仿函数

类似C语言的回调函数方法

template<class T, class contaier = vector<T>>
	class my_priorty_queue
	{
	public:
		my_priorty_queue(bool(*pf)(T, T))
			:a(*new contaier())
			,_pf(pf)
		{}
		void push(const T& num)
		{
			//尾插
			a.push_back(num);
			//建堆,向上调整
			upajust();


		}
		void pop()
		{
			//首尾交换
			std::swap(a[0], a[a.size() - 1]);
			//删除尾部
			a.pop_back();
			//向下调整
			downadjust();
		}
		void upajust()
		{
			this->a;
			//向上调整,建大堆
			int i = (this->a).size() - 1;
			while (i > 0)
			{
				if (_pf(a[i],a[(i - 1) / 2]))
				{
					std::swap(a[i], a[(i - 1) / 2]);
					i = (i - 1) / 2;
				}
				else
					break;
			}
		}
		void downadjust()
		{
			int father = 0;

			while (father < a.size())
			{
				//进行分类,如果没有孩子,只有一个孩子,两个孩子
				if (a.size() - 1 < 2 * father + 1)
					break;
				else if (a.size() - 1 < 2 * father + 2)
				{
					if (_pf(a[2 * father + 1], a[father]))
					{
						std::swap(a[father], a[2 * father + 1]);
					}
					else
						break;
				}
				else
				{
					int leftchila = 2 * father + 1;
					int rightchila = leftchila + 1;
					int pos = 0;
					//孩子比较大小
					if (_pf( a[rightchila], a[leftchila]))
					{
						pos = rightchila;
					}
					else
					{
						pos = leftchila;

					}
					//孩子和父亲比较
					if (_pf(a[pos] ,a[father]))
						std::swap(a[pos], a[father]);
					else
						break;
					father = pos;
				}
			}

		}
		bool empty()
		{
			return a.empty();
		}

		T top()
		{
			assert(a.size());
			return a[0];
		}

	private:
		contaier a;
		bool(*_pf)(T,T);

	};
	template<class T >
	bool funtionmin(T a, T b)
	{
		return a < b;
	}
	template<class T >
	bool funtionmax(T a, T b)
	{
		return a > b;
	}

这样写的话,就有点别扭,实例化要传入函数指针,这和我们使用库函数提供的差别很大

仿函数

本质就是一个类, 这个类重载了(), 可以理解为重载了()的类就是仿函数,
所以,仿函数的调用就是, 对象名(形参, 形参)
例如:

class AA
{
	void operator()(int a, int b)
	{
		cout << "a+b=" << a + b;
	}
};
int main()
{
	AA elemest;
	elemest(1,1);
	return 0;
}

模拟priority_queueu使用仿函数,如图所示,这也就解释了,为啥会有三个类模板参数了

template<class T, class contaier = vector<T> , class conpart = upsortjust<T>> 
	class my_priorty_queue
	{
	public:
		void push(const T& num)
		{
			//尾插
			a.push_back(num);
			//建堆,向上调整
			upajust();


		}
		void pop()
		{
			//首尾交换
			std::swap(a[0], a[a.size() - 1]);
			//删除尾部
			a.pop_back();
			//向下调整
			downadjust();
		}
		void upajust()
		{
			this->a;
			//向上调整,建大堆
			int i = (this->a).size() - 1;
			while (i > 0)
			{
				if (_pf(a[i],a[(i - 1) / 2]))
				{
					std::swap(a[i], a[(i - 1) / 2]);
					i = (i - 1) / 2;
				}
				else
					break;
			}
		}
		void downadjust()
		{
			int father = 0;

			while (father < a.size())
			{
				//进行分类,如果没有孩子,只有一个孩子,两个孩子
				if (a.size() - 1 < 2 * father + 1)
					break;
				else if (a.size() - 1 < 2 * father + 2)
				{
					if (_pf(a[2 * father + 1], a[father]))
					{
						std::swap(a[father], a[2 * father + 1]);
					}
					else
						break;
				}
				else
				{
					int leftchila = 2 * father + 1;
					int rightchila = leftchila + 1;
					int pos = 0;
					//孩子比较大小
					if (_pf(a[rightchila], a[leftchila]))
					{
						pos = rightchila;
					}
					else
					{
						pos = leftchila;

					}
					//孩子和父亲比较
					if (_pf(a[pos] ,a[father]))
						std::swap(a[pos], a[father]);
					else
						break;
					father = pos;
				}
			}

		}
		bool empty()
		{
			return a.empty();
		}

		T top()
		{
			assert(a.size());
			return a[0];
		}

	private:
		contaier a;
		conpart _pf;

	};
		template<class T>
		class upsortjust
		{
		public:
			bool operator()(const T& a, const T& b)
			{
				return a > b;
			}
		};
		template<class T>
		class downsortjust
		{
		public:
			bool operator()(const T& a, const T& b)
			{
				return a < b;
			}
		};

	};
小总结

可以看出,仿函数的使用和函数指针的使用是相似的,如果碰见仿函数对象传递的变量
例如:
在这里插入图片描述
sort函数的Compart comp 这个参数,也可以传函数指针,
如果不懂的话,也可以看我模拟的方法,

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

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

相关文章

极狐GitLab CICD Catalog Beta 功能介绍

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

【Python】数据类型之列表(下)

&#xff08;6&#xff09;清空列表 功能&#xff1a;clear() 代码示例&#xff1a; &#xff08;7&#xff09;根据值获取索引&#xff08;从左到右找到第一个返回索引&#xff09;【慎用&#xff0c;找不到报错】 功能&#xff1a;index(xyz)&#xff0c;xyz为数据类型。 …

OpenAI gym player mode

题意&#xff1a;OpenAI gym 的自定义模式 问题背景&#xff1a; Does anyone know how to run one of the OpenAI gym environments as a player. As in letting a human player play a round of cart pole? I have seen that there is env.mode human but I have not been…

波兰表达式求值

from operator import add, sub, muldef div(x, y):# 使用整数除法的向零取整方式return int(x / y) if x * y > 0 else -(abs(x) // abs(y))class Solution(object):op_map {: add, -: sub, *: mul, /: div}def evalRPN(self, tokens: List[str]) -> int:stack []for …

【C基础-按要求找数】一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少

一个整数&#xff0c;它加上100后是一个完全平方数&#xff0c;再加上168又是一个完全平方数&#xff0c;请问该数是多少 完全平方数是指一个整数能够表示为某个整数的平方。换句话说&#xff0c;如果存在一个整数 n&#xff0c;使得 n^2m,那么 m 就是一个完全平方数。 使用C…

第二十一天培训笔记

上午 1 、环境准备 2 、安装 mysql 绿包 3 、配置 mysql 工作环境 mysql -hip 地址 -p3306 -uroot -p &#xff08;远程连接使用&#xff09; 4 、 mysql 基础命令 &#xff08; 1 &#xff09;修改密码 &#xff08; 2 &#xff09;授权远程登录 &#xff08; 3 &#x…

程序员短视频上瘾综合症

一、是你疯了还是面试官疯了&#xff1f; ​ 最近有两个学员咨询问题&#xff0c;把我给整得苦笑不得。大家来看看&#xff0c;你有没有同样的症状。 ​ 第一个学员说去一家公司面试&#xff0c;第一轮面试聊得挺好的。第二轮面试自我感觉良好&#xff0c;但是被面试官给Diss…

模型优化学习笔记—对比各种梯度下降算法

import mathimport numpy as np from opt_utils import * import matplotlib.pyplot as plt# 标准梯度下降 def update_parameters_with_gd(parameters, grads, learning_rate):L len(parameters) // 2for l in range(1, L 1):parameters[f"W{l}"] parameters[f&q…

【uniapp】聊天记录列表长按消息计算弹出菜单方向

1. 效果图 1.1 消息靠上接近导航栏&#xff0c;菜单显在消息体下方弹出&#xff0c;箭头向上 1.2 消息体没有贴近上方导航栏&#xff0c;菜单在消息体上方弹出&#xff0c;箭头向下 1.3 长消息&#xff0c;菜单在手指按下的位置弹出&#xff0c;无箭头 2. 代码实现 <view …

sqli 1- 10

sql靶场 第一关 首先我们需要判断是否存在sql注入点&#xff0c;前端界面提示我使用ID作为参数,在url地址栏输入?id1 通过输入不同的id值查询数据库相对应的内容&#xff0c;之后判断为数字型还是字符型 根据查询内容判断为字符型且有注入点&#xff0c;再通过联合查询&…

Vitis AI 基本操作+模型检查(inspector)用法详解

目录 1. 简介 2. 代码详解 2.1 导入所需的库 2.2 创建 Inspector 2.3 下载模型 2.4 检查模型 3. 其他有用函数 3.1 查看 torchvision 中模型 3.2 保存模型 3.2.1 保存模型参数 3.2.2 保存完整模型 3.2.3 加载模型 4. 总结 1. 简介 在《Vitis AI 构建开发环境&…

GNSS相关知识

各定位系统的频段&#xff1a; SystemSignalFrequency(MHz)GPSL1C/A1575.42L1C1575.42L2C1227.6L2P1227.6L51176.45   GLONASSL1C/A1598.0625-1609.3125L2C1242.9375-1251.6875L2P1242.9375-1251.6875L3OC1202.025   GalileoE11575.42E5a1176.45E5b1207.14E5AltBOC1191.…

SpringBoot之外部化配置

前言 SpringBoot 版本 2.6.13&#xff0c;相关链接 Core Features Default properties (specified by setting SpringApplication.setDefaultProperties).PropertySource annotations on your Configuration classes. Please note that such property sources are not added …

如何在群晖NAS中搭建影音管理利器nastool并实现远程访问本地资源

文章目录 前言1. 本地搭建Nastool2. nastool基础设置3. 群晖NAS安装内网穿透工具4. 配置公网地址5. 配置固定公网地址 前言 Nastool是为群晖NAS玩家量身打造的一款智能化影音管理利器。它不仅能够满足电影发烧友、音乐爱好者和追剧达人的需求&#xff0c;更能让你在繁忙的生活…

疯狂的马达——Arduino

本次学习目标 1、了解马达的运用、以及马达内部的基本原理。 2、学会通过编程控制马达的速度、方向。 3、制作电位器换挡风扇。 马达 “马达”为英语motor的音译&#xff0c;我们称为电机&#xff0c;电机又可分为 发电机和电动机。前者是一种能够将动能转化电能的装置&am…

【知识】pytorch中的pinned memory和pageable memory

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 概念简介 pytorch用法 速度测试 反直觉情况 概念简介 默认情况下&#xff0c;主机 &#xff08;CPU&#xff09; 数据分配是可分页的。GPU 无…

计算机系统的基本结构-CSP初赛知识点整理

真题练习 [2021-CSP-J-第3题] 目前主流的计算机储存数据最终都是转换成&#xff08; &#xff09;数据进行储存。 A.二进制 B.十进制 C.八进制 D.十六进制 [2020-CSP-J-第1题] 在内存储器中每个存储单元都被赋予一个唯一的序号&#xff0c;称为( ) A&#xff0e;地址 B&a…

探索 Electron 应用的本地存储:SQLite3 与 Knex.js 的协同工作

electron 简介 Electron 是一个使用 JavaScript, HTML 和 CSS 构建跨平台桌面应用程序的框架。 它允许开发者使用 Web 技术来创建桌面软件&#xff0c;而不需要学习特定于平台的编程语言。 Electron 应用程序实际上是一个包含 Web 内容的 Chromium 浏览器实例&#xff0c;并…

创建型模式(Creational Patterns)之工厂模式(Factory Pattern)之简单工厂模式(Simple Factory Pattern)

1.简单工厂模式&#xff08;Simple Factory Pattern&#xff09;&#xff0c;又叫做静态工厂方法&#xff08;Static FactoryMethod Pattern&#xff09;。 1.1 基本介绍 被创建的对象称为“产品”&#xff0c;创建产品的对象称为“工厂”。如果要创建的产品不多&#xff0c;只…

WPF-实现多语言的静态(需重启)与动态切换(不用重启)

一、多语言切换&#xff08;需重启&#xff09; 1、配置文件添加Key <appSettings><add key"language" value"zh-CN"/></appSettings> 2、新增附加属性当前选择语言 public CultureInfo SelectLanguage{get > (CultureInfo)GetValu…