C++ queue 和priority_queue

目录

1.什么是queue

2.模拟实现

3.仿函数

模板参数Compare

仿函数

 4.什么是priority_queue

模拟实现


1.什么是queue

1.队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。


2.队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。


3.底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

4.标准容器类dequelist满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque

empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列

用法跟stack一样,可以看上一篇文章

2.模拟实现

queue.h

#include "string.h"
#include<iostream>
#include<stack>
#include<deque>


using namespace std;

namespace lty
{
	template<class T, class Container = deque<T>>
	class queue
	{
	public:

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

		void pop()
		{
			_con.pop_front();
		}

		T& front()
		{
			return _con.front();
		}

		T& back()
		{
			return _con.back();
		}

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

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

	private:
		Container _con;
	};

	void testqueue()
	{
		queue<int,deque<int>> q;
		q.push(1);
		q.push(2);
		q.push(3);
		q.push(4);
		q.push(5);

		while (!q.empty())
		{
			cout << q.front() << " ";
			q.pop();
		}
		cout << endl;

	}
}

queue.cpp

#include "queue.h"

using namespace std;

int main()
{
	lty::testqueue();
}

3.仿函数

模板参数Compare

#include <iostream>
#include <queue>

int main() {
    std::priority_queue<int> maxHeap; // 默认大堆

    std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap; // 小堆

    maxHeap.push(5);
    maxHeap.push(3);
    maxHeap.push(8);

    minHeap.push(5);
    minHeap.push(3);
    minHeap.push(8);

    std::cout << "Max Heap (Top element): " << maxHeap.top() << std::endl;
    std::cout << "Min Heap (Top element): " << minHeap.top() << std::endl;

    return 0;
}

 

仿函数

仿函数实际就是一个类,这里类实例化出来的对象叫做函数对象,下面命名空间wyn中的两个仿函数就分别是两个类,在使用时直接用类进行实例化对象,然后让对象调用()的运算符重载,这样我们看到的调用形式就非常像普通的函数调用,但实际上这里并不是函数调用,而是仿函数实例化出来的对象调用了自己的operator()重载成员函数。


 

namespace lty
{
	template <class T>
	class less
	{
	public:
		bool operator()(const T& x, const T& y)const
		{
			return x < y;
		}
	};
	
	template <class T>
	class greater
	{
	public://将仿函数放成public,要不然class默认是私有的
		bool operator()(const T& x, const T& y)const
		{
			return x > y;
		}
	};
}
int main()
{
	lty::less<int> lessFunc;
	lty::greater<int> greaterFunc;
	lessFunc(1, 2);
	//你以为这里是函数调用,但他其实是仿函数对象lessFunc调用了他的成员运算符重载()函数。
}

 4.什么是priority_queue

优先级队列的适配会更复杂一些些。它的适配容器用的是vector。

优先级队列就不是什么先进先出了,它虽然叫队列,但它不是真队列。其实它的底层是堆,可以在任意时刻插入数据,默认是大堆,当然也可以通过仿函数去调整。

优先级队列有一个反人类的设计:传less仿函数,底层是大堆。传greater仿函数,底层是小堆。

它的一些接口


priority_queue和queue以及stack一样,他们都是由底层容器适配出来的适配器,之不过priority_queue采用的适配容器不再是deque而是vector,选择vector的原因也非常简单,在调用向上或向下调整算法时,需要大量频繁的进行下标随机访问,这样的情境下,vector就可以完美展现出自己结构的绝对优势


模拟实现

#pragma once

namespace lty
{
	// Compare进行比较的仿函数 less->大堆
	// Compare进行比较的仿函数 greater->小堆
	template<class T, class Container = vector<T>, class Compare = std::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)
			{
				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 push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size() - 1);
		}

		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 pop()
		{
			std::swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();

			adjust_down(0);
		}

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

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

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

	private:
		Container _con;
	};
}

命名空间 xzq:
这段代码位于命名空间 xzq 中,这是一个自定义的命名空间,用于将相关的类、函数等封装在一起,以避免与其他代码的命名冲突。

模板类 priority_queue:
这是一个模板类,它代表了一个优先队列的实现。它接受三个模板参数:T(元素类型),Container(底层容器类型,默认为 std::vector<T>),和 Compare(用于比较元素的仿函数,默认为 std::less<T>)

Compare 是一个模板参数,用于进行元素的比较。它是一个仿函数,可以是 std::less<T>(默认)或 std::greater<T>,具体取决于用户提供的优先队列类型。Compare 仿函数用于确定在堆中的元素排序方式,从而决定了是最大堆还是最小堆。在 priority_queue 类的各个成员函数中,通过调用 Compare 仿函数来进行元素的比较,从而实现了插入和调整堆的操作。

构造函数 priority_queue():
这是一个默认构造函数,不需要使用 Compare 仿函数进行比较。

构造函数模板 priority_queue(InputIterator first, InputIterator last):
在构造函数内部,使用 Compare 仿函数来执行比较操作,以确定元素的顺序。在添加元素后,通过调用 adjust_down 函数来构建堆。

成员函数 adjust_up(size_t child):
在上浮操作中,使用 Compare 仿函数执行比较,以确定是否需要交换父子节点的位置,从而保持堆的性质。

成员函数 push(const T& x):
在插入操作中,首先将新元素添加到底层容器 _con,然后通过调用 adjust_up 函数来执行上浮操作,保证新元素位于合适的位置。

成员函数 adjust_down(size_t parent):
在下沉操作中,使用 Compare 仿函数执行比较,以确定是否需要交换父子节点的位置,从而保持堆的性质。

成员函数 pop():
在删除操作中,首先将顶部元素与底层容器的最后一个元素交换,然后通过调用 adjust_down 函数来执行下沉操作,保证堆的性质。

成员函数 const T& top():
通过返回 _con[0],获取优先队列的顶部元素。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

APP备案,最新获取安卓签名文件中MD5等信息方法

1.通过签名文件获取SHA1和SHA256 直接通过cmd执行命令 keytool -list -v -keystore xxxxx/xxx/xx/xxx.keystore输入后回车会提示输入密码库口令&#xff0c;直接输入Keystore密码&#xff08;输入过程中终端上不会显示&#xff0c;输完回车就行&#xff09; 2.获取md5 由于…

从线性回归到神经网络

一、线性回归关键思想 1、线性模型 2、基础优化算法 二、线性回归的从零开始实现 在了解线性回归的关键思想之后&#xff0c;我们可以开始通过代码来动手实现线性回归了。在这一节中&#xff0c;我们将从零开始实现整个方法&#xff0c;包括数据流水线、模型、损失函数和小批量…

js判断是否对象自身为空

文章目录 一、前言二、JSON.stringify三、for in 配合 hasOwnProperty四、Object.keys五、Object.getOwnPropertyNames六、Object.getOwnPropertyNames 结合 Object.getOwnPropertySymbols七、Reflect.ownKeys八、最后 一、前言 如何判断一个对象为空&#xff1f; 先上结论&a…

前端面试——CSS面经(持续更新)

1. CSS选择器及其优先级 !important > 行内样式 > id选择器 > 类/伪类/属性选择器 > 标签/伪元素选择器 > 子/后台选择器 > *通配符 2. 重排和重绘是什么&#xff1f;浏览器的渲染机制是什么&#xff1f; 重排(回流)&#xff1a;当增加或删除dom节点&…

深入理解Dubbo-3.高级功能剖析和原理解析

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理&#x1f525;如果感觉博主的文章还不错的话&#xff…

深入理解JavaScript的箭头函数

深入理解JavaScript的箭头函数 在ES6中&#xff0c;JavaScript引入了箭头函数的概念&#xff0c;它提供了一种更简洁的语法来定义匿名函数。虽然箭头函数看起来很简单&#xff0c;但它们在实际应用中有一些独特的特性和行为。让我们深入理解箭头函数并学习如何正确地使用它们。…

ES6之Map对象

ES6提供了 Map数据结构。它类似于对象&#xff0c;也是键值对的集合。但是“键”的范围不限于字符串&#xff0c;各种类型的值&#xff08;包括对象&#xff09;都可以当作键。 创建方法 let m new Map()console.log(m)Map的方法 1.set( ) 添加元素 接收两个参数&#xff0c…

iMazing 2.17.10官方中文版含2023最新激活许可证码

iMazing是一款iOS设备管理软件&#xff0c;界面简洁功能丰富&#xff0c;但其中还有一个界面更简洁&#xff0c;功能更精炼的小工具&#xff0c;适合轻量级的用户日常来使用&#xff0c;更加方便快捷。接下来&#xff0c;小编就来教大家如何使用iMazing MiNi&#xff0c;以及它…

2-2、基本数据类型

语雀原文链接 文章目录 1、数据类型分类2、基本数据类型2-1、布尔型boolean2-2、字符型char2-3、整型 byte short int long2-4、浮点型float double 3、基本类型转换byte特例char特例 1、数据类型分类 Java 语言是一种强类型语言。通俗点说就是&#xff0c;在 Java 中存储的数…

卡码网 46携带研究材料 LeetCode 416分割等和数组 1049最后一块石头的重量-ii | 代码随想录25期训练营day42、43

动态规划算法4 卡码网 46 携带研究材料 2023.12.6 题目链接常规二维dp数组方法代码随想录讲解[链接]一维滚动数组方法代码随想录讲解[链接] //二维dp数组做法 #include<bits/stdc.h> using namespace std;int main() {//m为材料种类数&#xff0c;n为行李箱最大空间数…

手眼标定 - 最终精度和误差优化心得

手眼标定 - 标定误差优化项 一、TCP标定误差优化1、注意标定针摆放范围2、TCP标定时的点次态与工作姿态尽可能保持相近 二、深度相机对齐矩阵误差1、手动计算对齐矩阵 三、手眼标定拍照姿态1、TCP标定姿态优先2、水平放置棋盘格优先 为减少最终手眼标定的误差&#xff0c;可做或…

首次发布亚马逊云科技生成式AI技术堆栈,re:Invent大会重磅发布

亚马逊云科技总是在不断重构&#xff0c;以推动创新&#xff0c;而今年re:Invent的主角毫无疑问是生成式AI。这从亚马逊云科技副总裁、首席布道师Jeff Barr在re:Invent 2023之前就迫不及待地写了一篇关于PartyRock的体验试玩教程即可窥见一斑。 事实也确实如此。在Las Vegas&am…

什么是HTML?

✨前言✨ 本文主要介绍什么是HTML以及W3C &#x1f352;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f352;博主将持续更新学习记录收获&#xff0c;友友们有任何问题可以在评论区留言 文章目录 什么是HTMLHTML发展史HTML的特点什么…

编程怎么学才能快速入门,分享一款中文编程工具快速学习编程思路,中文编程工具之分组框构件简介

一、前言&#xff1a; 零基础自学编程&#xff0c;中文编程工具下载&#xff0c;中文编程工具构件之扩展系统菜单构件教程 编程系统化教程链接 https://jywxz.blog.csdn.net/article/details/134073098?spm1001.2014.3001.5502 给大家分享一款中文编程工具&#xff0c;零基础…

Linux权限命令详解

Linux权限命令详解 文章目录 Linux权限命令详解一、什么是权限&#xff1f;二、权限的本质三、Linux中的用户四、linux中文件的权限4.1 文件访问者的分类&#xff08;人&#xff09;4.2 文件类型和访问权限&#xff08;事物属性&#xff09; 五、快速掌握修改权限的做法【第一种…

windows下分卷解压文件

我的文件是这样的&#xff1a; 存放路径为&#xff1a;C:\Users\Luli_study\MICCAI_MMAC\fudanuniversity\DDR dataset 首先要进入分卷文件的目录cd&#xff1a; 第一步&#xff1a;cd /path/o/分卷问文件目录 第二步&#xff1a; 执行之后的结果(红色框出来的)&#xff1a; …

如何掌握构建 LMS 网站的艺术

目录 什么是学习管理系统 (LMS) 在线课程和 LMS 网站的好处 为什么 WordPress 对于 LMS 网站很重要 统一学习中心 多功能性和可扩展性 提高教育参与度 简化管理和监控 节省时间和费用 技能评估和绩效监督 持续学习和技能提升 使用 WordPress 插件构建成功的 LMS 课程 专注于您的…

力扣257. 二叉树的所有路径(递归回溯与迭代)

题目&#xff1a; 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5] 输出&#xff1a;["1->2->5","…

【小白专用】Sql Server 连接Mysql 更新23.12.09

目标 已知mysql连接参数&#xff08;地址和用户&#xff09;&#xff0c;期望通过Microsoft Sql Server Management Studio &#xff08;以下简称MSSSMS&#xff09;连接Mysql&#xff0c;在MSSSMS中直接查询或修改Mysql中的数据。 一般是选最新的版本下载。 选64位还是32位&a…

java--包装类

1.包装类 ①包装类就是把基本类型的数据包装成对象。 ②自动装箱&#xff1a;基本数据类型可以自动转换为包装类型。 ②自动拆箱&#xff1a;包装类型可以自动转换为基本类型。 2.包装类的其他常见操作 ①可以把基本类型的数据换成字符串类型。 ②可以把字符串类型的数值转…