前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++初阶:容器适配器priority_queue常用接口详解及模拟实现、仿函数介绍

C++初阶:容器适配器priority_queue常用接口详解及模拟实现、仿函数介绍

作者头像
是Nero哦
发布2024-02-25 09:58:58
1870
发布2024-02-25 09:58:58
举报
文章被收录于专栏:c/c++学习与分享

1.priority_queue的介绍和使用

1.1priority_queue的初步介绍

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

1.2priority_queue的使用

函数声明

接口说明

priority_queue()

构造一个空的优先级队列

priority_queue(first, last)

构造一个优先级队列,包含范围为[first, last)的元素

empty()

检测优先级队列是否为空,是返回true,否则返回false

top()

返回优先级队列中最大(最小)元素,即堆顶元素

push(x)

在优先级队列中插入元素x

pop()

删除优先级队列中最大(最小)元素,即堆顶元素

代码语言:javascript
复制
#include<iostream>
#include<vector>
#include<queue>
using namespace std;

int main()
{
	priority_queue<int> pq;//这里默认是大堆
	pq.push(3);
	pq.push(2);
	pq.push(6);
	pq.push(9);
	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

	priority_queue<int, vector<int>, greater<int>> pq2;//这里传入一个类型greater<int>(马上就讲了)
	pq2.push(3);
	pq2.push(2);
	pq2.push(6);
	pq2.push(9);
	while (!pq2.empty())
	{
		cout << pq2.top() << " ";
		pq2.pop();
	}
	cout << endl;
	return 0;
}

1.3进一步补全介绍

优先队列(priority_queue)是一个特殊的队列,它根据元素的优先级进行排序,而不是按照它们被插入的顺序。在C++中,优先队列通常使用堆(heap)数据结构来实现,这使得它能够在==O(

logn

)的时间复杂度内对元素进行插入和删除操作,并能够以O(1)的时间复杂度获取队列中的最大(或最小)==元素。

以下是优先队列(priority_queue)的一些重要特性和接口:

  1. 构造函数
    • priority_queue<Type, Container, Compare>:创建一个优先队列对象,其中Type是元素类型,Container是底层容器类型(默认为vector),Compare是元素比较的函数对象类型(默认为std::less,用于最大堆)。
    • priority_queue(first, last):使用范围为[first, last)的迭代器构造一个优先队列。
  2. 默认行为
    • 默认情况下,优先队列是最大堆,即最大元素位于堆顶。可以通过自定义比较函数对象来改变这一行为,从而创建最小堆或者基于自定义的优先级规则进行排序。
  3. 底层实现
    • 在C++中,优先队列通常使用vector或deque作为底层容器,并通过堆算法来维护元素的顺序。

2.仿函数/函数对象讲解

函数对象(Functor)也称为仿函数(Function Object),是C++中的一种重要概念,它是一个行为类似函数的对象,可以被当作函数来调用。在C++中,函数对象可以以类的形式实现(其实是个类),重载operator()运算符,从而可以像函数一样被调用。 函数对象可以提供比普通函数更多的灵活性和功能,它可以保存状态、具有成员变量、可以在构造函数中接受参数等。函数对象通常用于STL中的算法、容器和适配器中,它们可以作为参数传递给算法,用于自定义排序、查找、比较等操作。

代码语言:javascript
复制
namespace FunctionObject
{
	template<class T>
	class less
	{
	public:
		bool operator()(const T& a, const T& b)
		{
			return a < b;
		}
	};

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

void test1()
{
	int a = 1;
	int b = 10;
	FunctionObject::greater<int> big;//定义一个对象
	cout << big(a, b) << endl;//只看big(a, b) 跟函数调用长得一样
}

int main()
{
	test1();
	return 0;
}

3.模拟priority_queue

文件规划和一览

priority_queue.h:用来实现queue test.cpp:进行测试

3.1模拟priority_queue(priority_queue.h)

代码语言:javascript
复制
#pragma once

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

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

	template<class T, class Container = vector<T>, class Compare = less<T>>//默认是大堆
	class priority_queue
	{
	public:

		void adjust_up(int child)
		{
			Compare com;
			int father = (child - 1) / 2;//得到父节点的索引
			while (child > 0)//再怎么向上也只能到0
			{
				if (com(_con[father], _con[child]))
				{
					swap(_con[father], _con[child]);
					child=father;
					father= (child - 1) / 2;//更新两个节点
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int father)
		{
			Compare com;
			int child = father * 2 + 1;//假设左孩子较大
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))//右孩子存在且比左孩子大
				{
					child++;
				}

				if(com(_con[father], _con[child]))
				{
					swap(_con[father], _con[child]);
					father=child;
					child = father * 2 + 1;//更新两个节点
				}
				else
				{
					break;
				}
			}
		}

		void push(const T& x)
		{
			_con.push_back(x);

			adjust_up(_con.size() - 1);
		}

	    //先交换后再向下调整
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();

			adjust_down(0);
		}

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

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

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

	private:
		Container _con;
	};
}

3.2测试(test.cpp)

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<queue>
using namespace std;

#include"priority_queue.h"

int main()
{
	MyPriority_queue::priority_queue<int> pq;//这里默认是大堆
	pq.push(3);
	pq.push(2);
	pq.push(6);
	pq.push(9);
	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

	priority_queue<int, vector<int>, MyPriority_queue::greater<int>> pq2;
	pq2.push(2);
	pq2.push(6);
	pq2.push(9);
	while (!pq2.empty())
	{
		cout << pq2.top() << " ";
		pq2.pop();
	}
	cout << endl;
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.priority_queue的介绍和使用
    • 1.1priority_queue的初步介绍
      • 1.2priority_queue的使用
        • 1.3进一步补全介绍
        • 2.仿函数/函数对象讲解
        • 3.模拟priority_queue
          • 文件规划和一览
            • 3.1模拟priority_queue(priority_queue.h)
              • 3.2测试(test.cpp)
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档