C++中priority_queue的使用与模拟实现

目录
  • priority_queue的使用
  • priority_queue简介
  • priority_queue的使用
  • priority_queue的模拟实现

priority_queue的使用

priority_queue文档介绍

priority_queue简介

  • 优先队列是一种容器适配器,有严格的排序标准,它的第一个元素总是它所包含的元素中最大的(或最小的)。
  • 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆(或 最小堆)元素(优先队列中位于顶部的元素)。
  • 默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。

priority_queue的使用

成员函数 功能
push 插入数据
pop 删除优先级队列中最大(最小)元素,即堆顶元素
top 返回优先级队列中最大(最小)元素,即堆顶元素
empty 检测优先级队列是否为空
size 获取队列中有效元素个数
void TestPriorityQueue()
{
	// 默认情况下,创建的是大堆,其底层按照小于号比较
	vector<int> v{ 3, 2, 7, 6, 0, 4, 1, 9, 8, 5 };
	priority_queue<int> q1;// 构建优先级队列
	for (auto e : v)
		q1.push(e);//尾插
	cout << "q1中元素个数:" << q1.size() << endl;
	for (size_t i = 0;i<v.size();++i)
	{
		cout << q1.top() << " ";//输出栈顶的数据
		q1.pop();//尾删
	}
	cout << endl;
	cout << "q1中元素个数:" << q1.size() << endl;
	cout << endl;
	// 如果要创建小堆,将第三个模板参数换成greater比较方式
	priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());
	for (size_t i = 0; i<v.size(); ++i)
	{
		cout << q2.top() << " ";//输出栈顶的数据
		q2.pop();//尾删
	}
	cout << endl;
}

如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供> 或者< 的重载。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	bool operator<(const Date& d)const
	{
		return (_year < d._year) ||
			(_year == d._year && _month < d._month) ||
			(_year == d._year && _month == d._month && _day < d._day);
	}
	bool operator>(const Date& d)const
	{
		return (_year > d._year) ||
			(_year == d._year && _month > d._month) ||
			(_year == d._year && _month == d._month && _day > d._day);
	}
	friend ostream& operator<<(ostream& _cout, const Date& d)
	{
		_cout << d._year << "-" << d._month << "-" << d._day;
		return _cout;
	}
private:
	int _year;
	int _month;
	int _day;
};
void TestPriorityQueue()
{
	// 大堆,需要用户在自定义类型中提供<的重载
	priority_queue<Date> q1;
	q1.push(Date(2022, 1, 7));
	q1.push(Date(2022, 1, 1));
	q1.push(Date(2022, 1, 31));
	cout << q1.top() << endl;
	cout << endl;
	// 如果要创建小堆,需要用户提供>的重载
	priority_queue<Date, vector<Date>, greater<Date>> q2;
	q2.push(Date(2022, 1, 7));
	q2.push(Date(2022, 1, 1));
	q2.push(Date(2022, 1, 31));
	cout << q2.top() << endl;
}

priority_queue的模拟实现

priority_queue的底层实际上就是堆结构,可以参考博主之前写的有关堆的文章数据结构之堆

namespace nzb
{
	//比较方式(使内部结构为大堆)
	template<class T>
	class Less
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};
	//比较方式(使内部结构为小堆)
	template<class T>
	class Greater
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};

	template<class T, class Container = vector<T>, class Compare = Less<T>>
	class  priority_queue
	{
	public:
		priority_queue()
		{}

		template<class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
		{
			//将迭代器中的数据插入优先级队列中
			while (first != last)
			{
				_con.push_back(*first);
				first++;
			}
			//从最后一个非叶子结点向上调整
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				AdjustDown(i);
			}
		}
		//堆的向上调整
		void AdjustUp(size_t child)
		{
			size_t parent = (child - 1) / 2;//找到父节点
			while (child > 0)
			{
				if (_com(_con[parent], _con[child]))//判断是否需要交换
				{
					//交换父子结点
					swap(_con[parent], _con[child]);
					//继续向上调整
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		//向下调整
		void AdjustDown(size_t parent)
		{
			size_t child = parent * 2 + 1;//算出左子节点的下标
			while (child < _con.size())
			{
				//找出子结点中符合比较方式的值
				if (child + 1 < _con.size() && _com(_con[child], _con[child + 1]))
				{
					child++;
				}
				//通过所给比较方式确定是否需要交换结点位置
				if (_com(_con[parent], _con[child]))
				{
					//交换父子结点
					swap(_con[parent], _con[child]);
					//继续向下调整
					parent = child ;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
		//插入数据
		void push(const T& x)
		{
			_con.push_back(x);
			AdjustUp(_con.size() - 1);//将最后一个元素向上调整
		}
		//删除数据
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);//交换首尾数据
			_con.pop_back();//尾删
			AdjustDown(0);//首元素向下调整
		}
		//访问头元素
		const T& top() const
		{
			return _con[0];
		}
		//获取队列中有效元素个数
		size_t size()
		{
			return _con.size();
		}
		//判空
		bool empty()
		{
			return _con.empty();
		}
	private:
		Container _con;//底层容器
		Compare _com;//比较方式
	};
}

到此这篇关于C++中priority_queue的使用与模拟实现的文章就介绍到这了,更多相关C++ priority_queue内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ 中"priority_queue" 优先级队列实例详解

    C++ 中"priority_queue" 优先级队列实例详解 1. 简介 标准库队列使用了先进先出(FIFO)的存储和检索策略. 进入队列的对象被放置在尾部, 下一个被取出的元素则取自队列的首部. 标准库提供了两种风格的队列: FIFO 队列(FIFO queue, 简称 queue), 以及优先级队列(priority queue). priority_queue 允许用户为队列中存储的元素设置优先级. 这种队列不是直接将新元素放置在队列尾部, 而是放在比它优先级低的元素前面. 标

  • C++中priority_queue模拟实现的代码示例

    目录 priority_queue概述 priority_queue定义 priority_queue特点 构造函数 修改相关函数 push pop 容量相关函数 size empty 元素访问相关函数 top 总结 priority_queue概述 priority_queue定义 优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最高优先权的元素. priority_queue特点 优先队列是一种容器适配器,首先要包含头文件 #include<queue>, 他和queu

  • C++ STL priority_queue自定义排序实现方法详解

    前面讲解 priority_queue 容器适配器时,还遗留一个问题,即当 <function> 头文件提供的排序方式(std::less<T> 和 std::greater<T>)不再适用时,如何自定义一个满足需求的排序规则. 首先,无论 priority_queue 中存储的是基础数据类型(int.double 等),还是 string 类对象或者自定义的类对象,都可以使用函数对象的方式自定义排序规则.例如: #include<iostream> #in

  • 详解c++优先队列priority_queue的用法

    既然是队列那么先要包含头文件#include <queue>, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队 优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的 和队列基本操作相同: top 访问队头元素 empty 队列是否为空 size 返回队列内元素个数 push 插入元素到队尾 (并排序) emplace 原地构造一个元素并插入队列 pop 弹出队头元素 swap 交换内容 定义:prio

  • c++优先队列(priority_queue)用法详解

    普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除. 在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有最高级先出 (first in, largest out)的行为特征. 首先要包含头文件#include<queue>, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队. 优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的. 和队列基本

  • C++ 容器适配器priority_queue的使用及实现代码

    优先级队列(Priority Queue) 队列是一种特征为FIFO的数据结构,每次从队列中取出的是最早加入队列中的元素.但是,许多应用需要另一种队列,每次从队列中取出的应是具有最高优先权的元素,这种队列就是优先级队列(Priority Queue),也称为优先权队列. 1. 优先级队列的概念 优先级队列的定义 优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最高优先权的元素. 优先级队列的特点 优先级队列是0个或多个元素的集合,每个元素都有一个优先权或值. 当给每个元素分配

  • C++中priority_queue的使用与模拟实现

    目录 priority_queue的使用 priority_queue简介 priority_queue的使用 priority_queue的模拟实现 priority_queue的使用 priority_queue文档介绍 priority_queue简介 优先队列是一种容器适配器,有严格的排序标准,它的第一个元素总是它所包含的元素中最大的(或最小的). 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆(或 最小堆)元素(优先队列中位于顶部的元素). 默认情况下,如果没有为特定的p

  • c++中vector的使用和模拟实现

    一.接口介绍 1.插入数据 void push_back(const T& x) 在当前vector尾部插入x,如果容量不够扩大二倍. iterator insert(iterator pos, const T& x) 在POS位置插入元素x 2.容量相关 size_t capacity() 返回当前vector的容量(size+剩余容量) size_t size() 返回当前vector的元素个数 void resize(size_t n, const T& val = T())

  • C语言中关于库函数 qsort 的模拟实现过程

    目录 前言 一.qsort函数 二.qsort函数实现思路 1. 底层原理 2. 函数传参 1). 第一个参数 2). 第二个参数 3). 第三个参数 4). 第四个参数 三.局部函数实现 四.全部代码汇集 五.总结 前言 我们在上一篇博客讲解了库函数qsort的使用,今天我为大家带来qsort的模拟实现.上一篇博客这个库函数的阅读链接:C语言中关于库函数 qsort 快排的用法 其实有人会问,我明明已经掌握了库函数qsort的使用方法,为何还要去写模拟实现,其实啊,学好一个东西,不仅仅只是会用

  • C++ 中"priority_queue" 优先级队列实例详解

    C++ 中"priority_queue" 优先级队列实例详解 1. 简介 标准库队列使用了先进先出(FIFO)的存储和检索策略. 进入队列的对象被放置在尾部, 下一个被取出的元素则取自队列的首部. 标准库提供了两种风格的队列: FIFO 队列(FIFO queue, 简称 queue), 以及优先级队列(priority queue). priority_queue 允许用户为队列中存储的元素设置优先级. 这种队列不是直接将新元素放置在队列尾部, 而是放在比它优先级低的元素前面. 标

  • C++中list的使用与模拟实现

    目录 一.list的介绍以及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list的迭代器失效 二.list的模拟实现 2.1 模拟实现list 总结 一.list的介绍以及使用 1.1 list的介绍 1.list是可以在常数范围内在任意位置进行插入和删除的序列式容器,

  • 详解C++中vector的理解以及模拟实现

    目录 vector介绍 vector常见函数介绍 vector模拟实现及迭代器失效讲解 vector介绍 vector文档 1.vector是表示可变大小数组的序列容器. 2.就像数组一样,vector也采用的连续存储空间来存储元素.也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效.但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理. 3.本质讲,vector使用动态分配数组来存储它的元素.当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间.其做

  • 仅Firefox中链接A无法实现模拟点击以触发其默认行为

    而标准的事件触发可以使用dispatchEvent方法.但现在FF5无法触发了A的默认行为了.如下 复制代码 代码如下: <!doctype html> <html> <head> <meta charset="utf-8"> <title>Firefox5链接A无法实现模拟点击bug</title> </head> <body> <a id="a1" href=&

  • DSP中浮点转定点运算--定点数模拟浮点数运算及常见的策略

    4.定点数模拟浮点数运算及常见的策略 相信大家到现在已经大致明白了浮点数转换成定点数运算的概貌.其实,原理讲起来很简单,真正应用到实际的项目中,可能会遇到各种各样的问题.具我的经验,常见的策略有如下几条: 1)除法转换为乘法或移位运算 我们知道,不管硬件平台如果变换,除法运算所需要的时钟周期都远远多于乘法运算和加减移位运算,尤其是在嵌入式应用中,"效率"显得尤为重要.以笔者的经验,其实,项目中的很大一部分除法运算是可以转换成乘法和移位运算,效率还是有很大提升空间的. 2)查表计算 有些

随机推荐