当前位置: 首页 > article >正文

priority_queue底层实现细节

一、priority_queue介绍

优先级队列只提供了 push() pop() top() 函数,本质是一个堆,所以只有堆顶的元素有意义。

本质也是容器适配器,用的是 vector,就像数据结构阶段实现的堆一样,但是由于模板的引入,在这里的优先级队列支持传入比较函数对象来实现不同情况的比较,从而使堆顶的 top 是符合要求的。

priority_queue 与 sort 的对比

两者都是通过传入比较函数对象来实现特定的比较,但是底层是不同的。

(1)priority_queue 是通过模板参数来接受收比较函数对象的,sort 函数是通过函数参数来接受比较函数对象的。

(2)所以一个是类模板传类型,一个是函数模板传对象。

二、部分代码展示

#pragma once
#include<vector>
using namespace std;
namespace bit
{
	template<class T>
	struct Less
	{
		bool operator(const T& x1, const T& x2)
		{
			return x1 < x2;
		}
	};

	template<class T>
	struct Greater
	{
		bool operator(const T& x1, const T& x2)
		{
			return x1 > x2;
		}
	};

	// 默认传递大堆,类模板传类型,函数模板传对象(要有())
	template<class T, class Container = vector<T>, class Cmp = Less<T>>
	class priority_queue
	{
	public:
		void adjustup(size_t child)
		{
			Cmp cmp;
			// 0 1 2
			int parent = (child - 1) / 2;
			while (child > 0) 
			{
				if (cmp(_con[parent], _con[child]))
				{
					std::swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
					break;
			}
		}
		void adjustdown(size_t parent)
		{
			Cmp cmp;
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && cmp(_con[child], _con[child + 1]))
					child++;
				if (cmp(_con[parent], _con[child]))
				{
					std::swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
					break;
			}
			
		}

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

		void pop()
		{
			std::swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			adjustdown(0);
		}
		
		bool empty()
		{
			return _con.size() == 0;
		}

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

		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

三、细节

push 和 pop 其实就是在维护一个堆,真正实现功能的是向上向下调整函数。

我们这里也和库一样实现两个比较类 Less 和 Greater,分别对应的是大堆和小堆。

要实现向上向下调整函数就一定要知道如何比较父子节点,此时比较类就可以通过模板参数来影响比较,实现功能。


http://www.kler.cn/a/514671.html

相关文章:

  • Linux(Centos 7.6)命令详解:iconv
  • 重学SpringBoot3-WebClient配置与使用详解
  • R语言基础| 回归分析
  • 【深度学习项目】语义分割-DeepLab网络(DeepLabV3介绍、基于Pytorch实现DeepLabV3网络)
  • 2025年入职/转行网络安全,该如何规划?网络安全职业规划
  • 京华春梦,守岁这方烟火人间
  • 图片生成Prompt编写技巧
  • ASP.NET Blazor部署方式有哪些?
  • 让旅游更智能:基于AR的旅游导览应用解析
  • jupyter notebook环境问题
  • 爬虫基础之爬取某站视频
  • VIVO大数据面试题及参考答案
  • PID 控制算法(二):C 语言实现与应用
  • KT148A语音芯片一个mp3语音,有办法分成一段一段的吗
  • typescript 书写.d.ts文件
  • 【ubuntu 连接显示器无法显示】可以通过 ssh 连接 ubuntu 服务器正常使用,但服务器连接显示器没有输出
  • AI新玩法:Flux.1图像生成结合内网穿透远程生图的解决方案
  • win暂停更新设置
  • react上增加错误边界 当存在错误时 不会显示白屏
  • Spring 中 Bean 是什么?从类到 Bean 的核心概念解析
  • SpringBoot对于Spring的扩展
  • 图论 n 皇后问题
  • Hadoop特点和HDFS命令
  • IP地址的格式有哪几类类型
  • vim在末行模式下的删除功能
  • MyBatis和JPA区别详解