【C++】STL之priority_queue类源码剖析

这篇具有很好参考价值的文章主要介绍了【C++】STL之priority_queue类源码剖析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

概述

算法

源码

PriorityQueue.h

test.cpp

测试结果


概述

priority_queue:优先级队列,包含在头文件<queue>中

优先级队列类似于堆结构,优先级最高的元素被置为堆顶,最优先被弹出top()和删除pop()

优先级队列的默认调整策略是大根堆,也就是最大值在堆顶

自定义类型需要用户自己提供 "<" 和 ">" 的重载才能使用优先级队列

元素的每一次插入push(),都是擦在队尾,再从队尾进行一次向上调整adjust_up()

元素的每一次删除pop(),都是删除堆顶元素(先将堆顶元素与末尾元素交换,再尾删),最后再从堆顶进行向下调整adjust_down()

算法

priority_queue优先级队列的设计,成员变量默认为一个vector容器变量,调整策略默认为less,这样大大简化了代码。

priority_queue优先级队列采用堆结构的设计方案,有其独特的特性,但每次插入删除都会进行调整,这样牺牲了部分性能。

用优先级队列调整自定义类型,需要自己提供 "<" 和 ">" 的重载

源码

PriorityQueue.h

#pragma once

#include <iostream>
#include <vector>

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

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

// 默认调整策略为 less,parent比child小则调整,建大根堆
template<class T,class Container = std::vector<T>, class Compare = Less<T>>
class PriorityQueue
{
public:
	PriorityQueue()
	{}

	template<class InputIterator>
	PriorityQueue(InputIterator first, InputIterator last)
		: _con(first, last)
	{
		for (size_t i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
		{
			adjust_down(i);
		}
	}

	void adjust_up(size_t child)
	{
		Compare com;
		size_t parent = (child - 1) / 2;
		while (child > 0)
		{
			if (com(_con[parent], _con[child]))
			{
				std::swap(_con[child], _con[parent]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
			{
				break;
			}
		}
	}
	void adjust_down(size_t parent)
	{
		Compare com;
		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]))
			{
				std::swap(_con[child], _con[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
			{
				break;
			}
		}
	}

	void push(const T& x)
	{
		_con.push_back(x);
		adjust_up(_con.size() - 1);
	}
	void pop()
	{
		std::swap(_con[0], _con[_con.size() - 1]);
		_con.pop_back();
		adjust_down(0);
	}

	const T& top()const
	{
		return _con[0];
	}
	bool empty()const
	{
		return _con.empty();
	}
	size_t size()const
	{
		return _con.size();
	}

private:
	Container _con;
};

test.cpp

#include "PriorityQueue.h"
#include <iostream>
using namespace std;

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
			&& _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);
	}
	bool operator>(const Date& d)const
	{
		return !(*this < d || *this == d);
	}

	friend ostream& operator<<(ostream& os, const Date& d)
	{
		os << d._year << "-" << d._month << "-" << d._day;
		return os;
	}

private:
	int _year, _month, _day;
};

struct PDateLess
{
	bool operator()(const Date* d1, const Date* d2)
	{
		return *d1 < *d2;
	}
};

struct PDateGreater
{
	bool operator()(const Date* d1, const Date* d2)
	{
		return *d1 > *d2;
	}
};

void Test()
{
	// 大堆,需要用户在自定义类型中提供 < 的重载
	PriorityQueue<Date> q1;
	q1.push(Date(2018, 10, 1));
	q1.push(Date(2019, 5, 20));
	q1.push(Date(2020, 2, 14));
	cout <<"q1.top = " << q1.top() << endl;
	while (q1.size())
	{
		cout << q1.top() << endl;
		q1.pop();
	}
	cout << endl;

	// 小堆,需要用户在自定义类型中提供 > 的重载
	PriorityQueue<Date, vector<Date>, greater<Date>> q2;
	q2.push(Date(2018, 10, 1));
	q2.push(Date(2019, 5, 20));
	q2.push(Date(2020, 2, 14));
	cout << "q2.top = " << q2.top() << endl;
	while (q2.size())
	{
		cout << q2.top() << endl;
		q2.pop();
	}
	cout << endl;

	PriorityQueue<Date*, vector<Date*>, PDateLess> q3;
	q3.push(new Date(2018, 10, 1));
	q3.push(new Date(2019, 5, 20));
	q3.push(new Date(2020, 2, 14));
	cout << "q3.top = " << *q3.top() << endl;
	while (q3.size())
	{
		cout << *q3.top() << endl;
		q3.pop();
	}
	cout << endl;

	PriorityQueue<Date*, vector<Date*>, PDateGreater> q4;
	q4.push(new Date(2018, 10, 1));
	q4.push(new Date(2019, 5, 20));
	q4.push(new Date(2020, 2, 14));
	cout << "q4.top = " << *q4.top() << endl;
	while (q4.size())
	{
		cout << *q4.top() << endl;
		q4.pop();
	}
	cout << endl;
}

int main()
{
	Test();

	return 0;
}

测试结果

【C++】STL之priority_queue类源码剖析

 文章来源地址https://www.toymoban.com/news/detail-432492.html

到了这里,关于【C++】STL之priority_queue类源码剖析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】STL使用仿函数控制优先级队列priority_queue

    本文章讲解C++STL的容器适配器:priority_queue的实现,并实现仿函数控制priority_queue底层。 priority_queue叫做优先级队列,它的底层结构是堆,在库中,默认生成的是大堆 在库的实现中,使用vector作为该优先级队列的适配容器。 由于priority_queue也是一个适配器,所以它的接口函数

    2024年02月16日
    浏览(48)
  • 【C++】STL优先级队列(priority_queue)功能介绍以及模拟实现

    点进来的小伙伴不知道学过数据结构里的堆没有,如果学过的话,那就好说了,优先级队列就是堆,如果没学过,没关系,可以参考一下我之前写的一篇关于堆的博客,可以点进去看看:【数据结构】堆(包含堆排序和TOPK问题) 那么了解过堆了的话,我就不讲那么细致了,

    2024年02月16日
    浏览(49)
  • 容器适配器---deque和STL ---stack queue priority_queue的模拟实现 C++

    目录 一、容器适配器 deque原理 deque的缺陷 deque的优势 二、stack的模拟实现  三、queue的模拟实现 四、优先级队列的模拟实现 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户

    2024年02月02日
    浏览(55)
  • 【C++】STL中的容器适配器 stack queue 和 priority_queue 的模拟实现

    适配器是一种设计模式 (设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。 例如我们常见的充电器就是一种适配器,它将我们常用的220V交流电压转化为4,5V (或者其他更高的电

    2023年04月26日
    浏览(61)
  • 【STL】priority_queue(优先级队列)详解及仿函数使用(附完整源码)

    1. priority_queue介绍和使用 1.1 priority_queue介绍 优先级队列也是在 queue 里: 因此和 queue 一样, priority_queue 也是一个容器适配器。priority_queue官方文档 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。 类似于堆,在堆中可以随

    2024年02月08日
    浏览(42)
  • 【C++】STL——容器适配器priority_queue(优先级队列)详解 及 仿函数的介绍和使用

    这篇文章我们接着上一篇的内容,再来学一个STL里的容器适配器—— priority_queue (优先级队列) 1.1 priority_queue的介绍 我们上一篇文章学了 queue (队列),那优先级队列也是在 queue 里面的: 和 queue 一样, priority_queue 也是一个容器适配器,那他和 queue 有什么区别呢?我们一

    2024年02月07日
    浏览(48)
  • 【C++初阶】仿函数和priority_queue的模拟实现(附源码)

    仿函数,顾名思义就是 模仿函数,它其实是一个类,类里面重载了运算符() ,在调用这个重载的运算符时,让我们感觉是调用函数一样,可以说相当于C语言里的函数指针一样,但是函数指针的可读性不好,不如仿函数。 1.仿函数即使定义相同,也可能有不同的类型; 2.仿

    2024年02月16日
    浏览(33)
  • STL之priority_queue与仿函数

    1.介绍 函数对象,又称仿函数,是可以像函数一样使用的对象,其原理就是重载了函数调用符: () 因此在此类中,一定有 operator() 的成员函数。 2.示例 如果T是内置类型,则直接进行比较。如果T是自定义类型,则会调用其operator()。 先创建一个_less类型的对象smaller,对于sma

    2024年02月10日
    浏览(41)
  • 【STL】priority_queue的使用及模拟实现

    目录 前言 priority_queue的使用 功能解析 基本接口 写点题目 模拟实现 结构解析 插入删除 调整函数结合仿函数 仿函数介绍 结合使用 其他功能 接口补齐 迭代器区间构造 🍾打开 queue 头文件后,我们发现除了我们之前介绍过的普通队列以外,还有一个 priority_queue 。 🍾其又名为

    2024年02月08日
    浏览(40)
  • 【STL详解 —— priority_queue的使用与模拟实现】

    std::priority_queue 是 C++ 标准库中的容器适配器,它提供了一种基于堆的优先级队列实现。优先级队列是一种特殊的队列,其中的元素按照一定的优先级顺序排列,而不是按照它们被插入的顺序。 在 std::priority_queue 中,插入元素时会根据元素的值自动进行排序,最大(或最小)

    2024年04月17日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包