【CPP】优先级队列

news2024/9/17 9:11:55

目录

  • 1.什么是优先级队列???
  • 2.优先级队列的基本使用与理解
  • 3.优先级队列的模拟实现

今天来简单分享一下写一个极简版的优先级队列。

1.什么是优先级队列???

在这里插入图片描述

优先级队列属于STL中队列的一种,虽然包含在队列容器里,但它并不是真正的队列。
在本质上,优先级队列更像一个堆,默认是大堆。
链接:LINK

下面我们简单来认识一下优先级队列的基本使用。

2.优先级队列的基本使用与理解

优先级队列的主要接口有下面这些:
在这里插入图片描述

// 优先级队列,默认底层是大堆。
priority_queue<int> ps;
ps.push(2);
ps.push(3);
ps.push(4);
ps.push(1);

while (!ps.empty())
{
	cout << ps.top() << " ";
	ps.pop();
}

在这里插入图片描述
那可以让他变成小堆吗?当然可以。但是需要用到仿函数。

// 优先级队列,可以用仿函数置为小堆
priority_queue<int, vector<int>, greater<int>> pq;
pq.push(2);
pq.push(3);
pq.push(4);
pq.push(1);

while (!pq.empty())
{
	cout << pq.top() << " ";
	pq.pop();
}

在这里插入图片描述

这里区分两个概念:取出结果是有序与真正排序的区别。
在上面优先级队列中,我们发现while+top取出的数据是有序的,这是因为我们每次取得都是堆顶元素。至于怎么弄的,可以参考C数据结构钟堆删除数据时候得操作,首尾交换,然后size–,我觉得应该是相同的操作。
在这里插入图片描述

// 我们发现sort默认排序为升序。
vector<int> v = { 1,3,4,2 };
vector<int>::iterator it = v.begin();
while (it != v.end())
{
	cout << *it << " ";
	it++;
}
cout << endl;

sort(v.begin(), v.end());
it = v.begin();
while (it != v.end())
{
	cout << *it << " ";
	it++;
}

在这里插入图片描述
为了让sort变成升序,我们也可以用仿函数进行设置。

vector<int> v = { 1,3,4,2 };
vector<int>::iterator it = v.begin();
while (it != v.end())
{
	cout << *it << " ";
	it++;
}
cout << endl;

sort(v.begin(), v.end(), greater<int>());
it = v.begin();
while (it != v.end())
{
	cout << *it << " ";
	it++;
}

在这里插入图片描述

重点区分一个地方:模板参数与函数参数的需要
priority_queue<int, vector<int>, greater<int>> pq;
sort(v.begin(), v.end(), greater<int>());
我们发现两个greater一个带括号一个不带,这是什么情况呢?

要注意优先级队列是一种模板,需要的是类型进行实例化,而sort是模板实例化出来的一种函数,需要迭代器区间和具体的比较仿函数对象,而不是仅仅一个仿函数类型就行。

3.优先级队列的模拟实现

#pragma once
#include<vector>
#include<iostream>
using namespace std;

template<typename T>
struct Less
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};

template<typename T>
struct Greater
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}
};

template<class T, class Container = vector<T>, class Compare = Greater<T>>
class periority_queue
{
private:
	Container _con;
public:
	void adjust_up(int child)
	{
		Compare com;
		int parent = (child - 1) / 2;

		while (child > 0)
		{
			if (com(_con[child], _con[parent]))
			{
				swap(_con[child], _con[parent]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
			{
				break;
			}
		}
	}

	void push(const T& x)
	{
		_con.push_back(x);
		adjust_up(_con.size() - 1);
	}

	void adjust_down(int parent)
	{
		Compare com;
		int child = parent * 2 + 1;
		while (child < _con.size())
		{
			if (child + 1 < _con.size() && com(_con[child + 1], _con[child]))
			{
				child = child + 1;
			}

			if (com(_con[child], _con[parent]))
			{
				swap(_con[child], _con[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
			{
				break;
			}
		}
	}

	void pop()
	{
		swap(_con[0], _con[_con.size() - 1]);
		_con.pop_back();
		adjust_down(0);
	}

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

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

	const T& top()
	{
		return _con[0];
	}
};

其实大部分接口实现都是复用vector的,但是插入和删除接口的逻辑还需要重点看一下。整体没什么难点,需要注意的是我们实现用了一个comper的东西去控制是建小堆/大堆。
comper传的是仿函数类型。我们在向上/向下调整算法中使用这个仿函数类型生成了仿函数(函数对象)进行控制。

引入仿函数的意义:
在本实例中,仿函数是用来控制是建大堆/小堆的,我们C语言可以传函数指针来控制,这个CPP的话比较习惯用仿函数,说白了就是传入一个特殊类对象来控制,感觉无论是C语言的传函数指针还是CPP传仿函数如果控制得当都挺好用,当然前提是C语言那个指针得玩的明白。CPP这个算是一种难度降低吧,毕竟函数指针有时候会弄错。


EOF

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

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

相关文章

vi编辑器的使用

vi 编辑器 vi是Linux中最基本的编辑器。但vi编辑器在系统管理、服务器配置工作中永远都是无可替代的。 一、vi的三种模式及模式切换命令 1、命令行模式 用户在用vi编辑文件时&#xff0c;最初进入的为该模式。可以进行复制、粘贴等操作。 2、插入模式 进行文件编辑&#xf…

【计算机情绪分析】十大数据集合集!宝藏合集,速看!

本文将为您介绍10个经典、热门的数据集&#xff0c;希望对您在选择适合的数据集时有所帮助。 1 AWARE 发布方&#xff1a; Imam Abdulrahman Bin Faisal University法赫德国王石油与矿产大学 发布时间&#xff1a; 2021-09-26 简介&#xff1a; AWARE 数据集的同行评审论文发…

Maven实战.插件

文章目录 插件目标插件绑定内置绑定自定义绑定 插件配置命令行插件配置POM中插件全局配置POM中插件任务配置 插件目标 在进一步详述插件和生命周期的绑定关系之前&#xff0c;必须先了解插件目标&#xff08;PluginCoal&#xff09;的概念。我们知道&#xff0c;Maven 的核心仅…

外星人入侵_计分

外星人入侵_计分 1添加Play按钮1.1创建Button类1.2在屏幕上绘制按钮1.3开始游戏1.4 重置游戏1.5 将Play按钮切换到非活动状态1.6隐藏光标 2提高等级2.1修改速度设置2.2重置速度 3计分3.1显示得分3.2创建记分牌3.3在外星人被消灭时更新得分3.4将消灭的每个外星人的点数都计入得分…

Linux:shell命令

Linux&#xff1a;shell命令 Shell echo命令 显示普通字符串 echo "i am wsf"显示转义字符 echo "i\" am usf"显示变量 read name#相当于python中的input echo "${name} is a name"read -p "请输入您的名字&#xff1a;" names#提…

怎么用U盘重装系统

在使用电脑的过程中&#xff0c;难免会遇到系统故障、运行缓慢等问题。当这些问题严重影响使用电脑的体验时&#xff0c;重装系统往往是一个有效的解决办法。用U盘重装系统是一种简单快捷的方法&#xff0c;本文将详细介绍如何使用U盘来重装系统&#xff0c;帮助大家轻松完成这…

推荐|代码签名证书怎么选?EV还是OV?

代码签名证书支持给.exe&#xff0c;.cab&#xff0c;.dll&#xff0c;.ocx&#xff0c;.msi&#xff0c;.xpi&#xff0c;.xap 等软件、控件进行数字签名!在选择代码签名证书时&#xff0c;EV和OV是两种常见的选择。这两种证书都用于对软件或应用程序进行数字签名。应该如何选…

在线短剧APP开发,短剧市场的新赛道新盈利

近几年中&#xff0c;短剧行业规模飞速上涨&#xff0c;越来越多的入局者开始进入市场&#xff0c;随着短剧市场的不断升温&#xff0c;也衍生出了短剧APP&#xff0c;为行业的发展带来了新的赛道&#xff01; 短剧APP的出现为观众提供了一个专属的短剧“港湾”&#xff0c;让…

探索智慧园区的创新实践与未来展望

智慧园区是指运用物联网、大数据、云计算、人工智能等新一代信息技术&#xff0c;对园区进行全方位、全时段的智能化改造&#xff0c;实现管理高效、服务便捷、环境友好、创新驱动的现代化园区形态。其核心理念在于通过技术赋能&#xff0c;优化资源配置&#xff0c;提升园区运…

基于MT76X8平台的Mtk-openwrt-sdk配置单网口方法

一、配置. 在SDK的工程下&#xff0c;运行make kernel_menuconfig&#xff0c;如下图所示&#xff1a; Ralink Module --->选上“One Port Only”&#xff0c;如下图所示&#xff1a; 如果P0网口实现WAN口&#xff0c;就配置成W/LLLL,否则就配置成LLLL/W. 二、修改网口的…

Camera Raw 修图简明教程

Adobe Camera Raw&#xff08;简称为 ACR &#xff09;是 Adobe 开发的一款强大插件&#xff0c;专为处理和编辑相机原始文件&#xff08;Raw 格式&#xff09;而设计&#xff0c;旨在帮助摄影师和图像编辑人员实现高质量的转码和图像处理。 如果想用 Camera Raw 处理 JPEG、TI…

使用C++和Mysql进行图像存取操作记录

使用C和Mysql进行图像存取操作记录 配置&#xff1a; 1.Mysql 5.5.19 2.Vs2019 3.C 一、创建图像存储表格 选择数据库指令&#xff1a; 将databasename改成你想操作的数据库就行。我这边依旧在student_manager数据库下进行操作。 use databasename;CREATE TABLE images(im…

知迪动态丨北斗智联领导团队莅临知迪科技上海研发中心

7月29日&#xff0c;北斗智联领导团队来到知迪科技参观考察。知迪科技总裁周强先生率公司管理层与技术代表热情接待。 北斗智联一行在知迪科技公司团队的陪同下&#xff0c;首先观摩了在技术展示区陈列的车辆数据记录设备、总线信号分析及仿真设备、ADAS HiL测试台架、测试自动…

【PostGresql】---- pgSql 将列中合并字符串拆分为多行 实例代码

-- 将 AQY_ID,AQY 中的字符串拆分为多行 SELECT"ID","AQY_ID","AQY",UNNEST ( string_to_array( "AQY_ID", , ) ) AS "AQY_ID_1",UNNEST ( string_to_array( "AQY", , ) ) AS "AQY_1" FROM"JF_SGC…

科目一考试题库(超全)!7分钟一把过科目一(总结经验)

1、先看视频 先了解考试规范、流程以及重要的考点难点&#xff0c;做到心中有数&#xff0c;大部分人觉得重难点在扣分题和罚款题上面&#xff0c;可以在网上看一些视频讲解&#xff0c;1.5倍速快速过一遍看的过程中记录一些笔记&#xff0c;可以随便看的而且真滴有用 2、认真刷…

教你如何从Flink小白成为Contributor最终拿到腾讯的Offer

简言&#xff1a;一开始我也是怀揣着成为一个技术大老的梦想开始的&#xff0c;尽管我现在已经入职腾讯三年多了有时候觉得自己还是一个菜鸡哈..... 写这个文章希望可以帮助到刚刚接触大数据&#xff0c;并且对技术怀揣着梦想的朋友们&#xff0c;大家互相学习哈(对Flink不是很…

成都云飞浩容文化传媒有限公司领航电商新纪元

在数字经济浪潮汹涌的今天&#xff0c;电商行业作为时代的弄潮儿&#xff0c;正以前所未有的速度改变着商业版图。成都&#xff0c;这座历史悠久而又充满活力的城市&#xff0c;正孕育着一家在电商服务领域独树一帜的企业——成都云飞浩容文化传媒有限公司。作为一家深耕电商服…

Linux系统编程(4):消息队列

Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。 而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室 以及 BSD&#xff08;加州大学伯克利分校的伯克利软件发布中心&#xff09;&#xff0c; 他们在进程间通信方面的侧重点有所不同&#xff1b; 前…

歌唱比赛活动策划方案书

&#xff08;一&#xff09;海选 1、时间&#xff1a;12月16日 2、地点&#xff1a;公司食堂 3、比赛评委设置&#xff1a;共计6名评委。 4、比赛规则&#xff1a; &#xff08;1&#xff09;选手按报名顺序及上报歌曲进行清唱&#xff08;限时2分钟&#xff0c;类型…