【C++】queue和priority_queue

news2024/9/22 15:48:59

在这里插入图片描述

个人主页~


queue和priority_queue

  • 一、queue的介绍和使用
    • 1、queue的介绍
    • 2、queue的使用
    • 3、queue的模拟实现
  • 二、priority_queue的介绍和使用
    • 1、priority_queue的介绍
    • 2、priority_queue的使用
    • 3、priority_queue的模拟实现
  • 三、仿函数
    • 1、仿函数的特征
    • 2、仿函数的使用
  • ex、有关于list反向迭代器

一、queue的介绍和使用

1、queue的介绍

queue详解

队列是一种容器适配器,专门用在先进先出操作中,从容器一端插入元素,另一端提取元素

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

底层容器至少要支持empty判空、size大小、front队头、back队尾、push_back尾插、pop_front头删操作

vector是没有办法满足以上操作的,但deque和list是可以的

2、queue的使用

函数声明接口说明
queue构造空队列
empty检测队列是否为空
size返回队列中有效数字个数
front返回队头元素的引用
back返回队尾元素的引用
push在队尾将元素入队
pop将队头元素出队列
void test_queue()
{
	std::queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	std::cout << q.size() << std::endl;
	std::cout << q.back() << std::endl;
	while (!q.empty())
	{
		std::cout << q.front() << " ";
		q.pop();
	}
}

在这里插入图片描述

3、queue的模拟实现

namespace little_monster
{
	template<class T,class Container = std::deque<T>>
	class queue
	{
	public:
		queue() 
		{}
		void push(const T& x) 
		{
			_c.push_back(x); 
		}
		void pop() 
		{
			_c.pop_front(); 
		}
		T& back() 
		{
			return _c.back(); 
		}
		const T& back()const 
		{
			return _c.back(); 
		}
		T& front() 
		{
			return _c.front(); 
		}
		const T& front() const 
		{
			return _c.front(); 
		}
		size_t size() const 
		{
			return _c.size(); 
		}
		bool empty() const 
		{
			return _c.empty(); 
		}
	private:
		Container _c;
	};
}

在这里插入图片描述
当然queue的第二个模版参数只能为deque和list,vector是不行的,因为pop_front不是vector的成员
在这里插入图片描述

二、priority_queue的介绍和使用

1、priority_queue的介绍

文档介绍

优先队列priority_queue是一种容器适配器,根据严格的弱排序标准,会变为降序队列

类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素

优先队列被实现为容器适配器,提供一组特定的成员函数来访问其元素,元素从特定容器的尾部弹出

底层容器需要支持empty、size、front、push_back、pop_back操作

标准容器vector、deque满足上述要求,但默认一般为vector

需要支持随机访问迭代器,以便始终在内部保持堆结构,容器适配器在需要时自动调整结构

2、priority_queue的使用

优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置都可以考虑使用priority_queue,默认状态下为大堆

函数声明接口说明
priority_queue()/priority_queue(first,last)构造一个空的优先级队列
empty判空
top返回堆顶元素
push在堆中插入元素
pop删除堆顶元素
#include <queue>
#include <functional>//里边有greater比较方式
void TestPriorityQueue()
{
	// 默认情况下,创建的是大堆,其底层按照小于号比较
	std::vector<int> v{ 3,2,7,6,0,4,1,9,8,5 };
	std::priority_queue<int> q1;
	for (auto& e : v)
		q1.push(e);
	// 如果要创建小堆,将第三个模板参数换成greater比较方式
	std::priority_queue<int, std::vector<int>, 
	std::greater<int>> q2(v.begin(), v.end());
	
	while(!q1.empty())
	{
		std::cout << q1.top() << " ";
		q1.pop();
	}
	std::cout << std::endl;

	while(!q2.empty())
	{
		std::cout << q2.top() << " ";
		q2.pop();
	}
	std::cout << std::endl;
}

在这里插入图片描述

如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中自己重载符号,就比如说日期类就要重载>、<,按照我们定义的方式进行比较

手感火热做道题
数组中的第K个最大元素

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        // 将数组中的元素先放入优先级队列中
        priority_queue<int> p(nums.begin(), nums.end());
        // 将优先级队列中前k-1个元素删除掉
        for (int i = 0; i < k - 1; ++i) 
        {
            p.pop();
        }
        return p.top();
    }
};

3、priority_queue的模拟实现

优先级队列就是一个封装好的堆

#pragma once
#include <vector>
namespace little_monster
{
	template <class T>
	struct less
	{
		bool operator()(const T& left, const T& right)
		{
			return left < right;
		}
	};
	template <class T>
	struct greater
	{
		bool operator()(const T& left, const T& right)
		{
			return left > right;
		}
	};

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

		template <class Iterator>
		priority_queue(Iterator first, Iterator last)
			: _c(first, last)
		{
			int count = _c.size();
			int root = ((count - 2) >> 1);
			for (; root >= 0; root--)
			{
				AdjustDown(root);
			}
		}
		void push(const T& x)
		{
			_c.push_back(x);
			AdjustUp(_c.size() - 1);
		}

		void pop()
		{
			if (empty())
				return;
			std::swap(_c.front(), _c.back());
			_c.pop_back();
			AdjustDown(0);
		}

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

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

		const T& top() const
		{
			return _c.front();
		}

	private:
		void AdjustDown(int parent)
		{
			size_t child = 2 * parent + 1;
			while (child < _c.size())
			{
				if (child + 1 < _c.size() 
				&& Compare()(_c[child], _c[child + 1]))
				{
					++child;
				}
				if (Compare()(_c[parent], _c[child]))
				{
					std::swap(_c[child], _c[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
					return;
			}
		}

		void AdjustUp(int child)
		{
			size_t parent = ((child - 1) >> 1);
			while (child)
			{
				if (Compare()(_c[parent], _c[child]))
				{
					std::swap(_c[parent], _c[child]);
					child = parent;
					parent = ((child - 1) >> 1);
				}
				else
					return;
			}
		}

	private:
		Container _c;
	};
}

在这里插入图片描述

我们自己定义less和greater以控制是大堆还是小堆,封装在一个结构体中,作为priority_queue的第三个模版参数

主要的就是向上调整算法和向下调整算法,与之前C语言学过的一样,稍有改变

三、仿函数

1、仿函数的特征

优先级队列中的less和greater叫做仿函数

重载圆括号运算符:仿函数的核心在于它重载了圆括号"()"运算符,这使得类的实例能够接收参数,并返回一个值

灵活性和状态保存:与普通函数相比,仿函数具有更大的灵活性,因为它可以包含成员变量,这意味着在多次调用仿函数时,它可以保持并更新这些状态信息,从而影响其行为或返回值

2、仿函数的使用

仿函数实际上就是重载括号,使用起来跟函数指针类似,它不仅能够像函数一样被调用,又具有类和对象的特性,像我们之前如果写向上调整算法以及向下调整算法,大堆和小堆是需要到算法中修改代码的,但是有了仿函数就可以直接重载()然后直接调整是less还是greater就好了

ex、有关于list反向迭代器

template<class Iterator, class Ref, class Ptr>
class ReverseIterator
{
public:
	typedef ReverseIterator<Iterator, Ref, Ptr> Self;

	ReverseIterator(Iterator it)
		:_it(it)
	{}

	Self& operator++()
	{
		--_it;
		return *this;
	}

	Self& operator--()
	{
		++_it;
		return *this;
	}

	Ref operator*()
	{
		Iterator cur = _it;
		return *(--cur);
	}

	Ptr operator->()
	{
		return &(operator*());
	}

	bool operator!=(const Self& s)
	{
		return _it != s._it;
	}

	bool operator==(const Self& s)
	{
		return _it == s._it;
	}
private:
	Iterator _it;
};

对正向迭代器进行封装就可以得到反向迭代器,先有正向再有反向


今日分享就到这里了~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

完结马哥教育SRE课程--基础篇

文章目录 一、Linux基础入门1.Linux基本架构2.什么是shell3.命令执行过程4.Shell中的两类命令5.常见命令6.输出信息echo7.tab键补全8.获取帮助 二、文件管理和IO重定向1.文件系统目录结构2.文件系统目录功能3.linux下的文件类型4.文件操作命令5.文件状态stat6.确定文件内容7.文…

【webpack4系列】webpack基础用法(二)

文章目录 entryoutputloaderpluginmode前端构建基础配置关联HTML插件html-webpack-plugin构建 CSS 解析 ES6和React JSX解析 ES6解析 React JSX 解析CSS、Less和Sass解析CSS解析Less解析sass 解析图片和字体资源解析&#xff1a;解析图片资源解析&#xff1a;解析字体资源解析&…

系统 IO

"裸奔"层次&#xff1a;不带操作系统的编程 APP(应用程序) -------------------------------- Hardware(硬件) 特点&#xff1a;简单&#xff0c;应用程序直接操作硬件(寄存器) 缺点&#xff1a; 1. 搞应用开发的必须要了解硬件的实现细节&#xff0c;能够看懂原理图…

Depth靶机详解

靶机下载地址 https://www.vulnhub.com/entry/depth-1,213/ 主机发现 arp-scan -l 端口扫描 nmap -sV -A -T4 192.168.229.156 端口利用 http://192.168.229.156:8080/ 目录扫描 dirb "http://192.168.229.156:8080" dirsearch -u "http://192.168.229.15…

UDP_SOCKET编程实现

文章目录 socket编程接口认识struct sockaddr类 编写一个server服务Client代码查看启动结果代码修正1.获取内核分配给客户端的信息2.修正不匹配ip不能访问的问题 不同机器之间的通信利用xftp将udp_client传给wsl的ubuntu机器进行演示现在模拟在windows下的udp_client代码: 对方…

松材线虫多光谱数据集

松材线虫多光谱数据集 无人机&#xff1a;dji mavic3 mutispectral 波段&#xff1a;red green rededge nir rgb 面积&#xff1a;39.05平方公里 数据&#xff1a;rgb影像&#xff0c;四个单波段影像&#xff0c;NDVI GNDVI LCI NDRE OSAVI 5个指数图 分辨率&#xff1a;0.03&a…

【智路】智路OS 欢迎来到智路OS路侧操作系统开发手册

https://airos-edge.readthedocs.io/zh/latest/ 欢迎来到智路OS路侧操作系统开发手册 智路OS 是一套完整的软件和服务开放系统&#xff0c; 由路侧操作系统&#xff08;airos-edge&#xff09;&#xff0c;车端&#xff08;airos-vehicle&#xff09;和云端开发者平台共同构成…

【Spring Boot】SpringBoot自动装配-Import

目录 一、前言二、 定义三、使用说明3.1 创建项目3.1.1 导入依赖3.1.2 创建User类 3.2 测试导入Bean3.2.1 修改启动类 3.3 测试导入配置类3.3.1 创建UserConfig类3.3.2 修改启动类 3.4 测试导入ImportSelector3.4.1 创建UseImportSelector类3.4.2 修改启动类3.4.3 启动测试 3.5…

Python 二维码(QR码)生成器:使用python-qrcode简化条码创建

在数字时代&#xff0c;QR码已成为快速信息共享和数据传输的必备工具。无论是用于市场营销活动、活动签到&#xff0c;还是仅仅分享Wi-Fi凭证&#xff0c;QR码都提供了一种方便的方式来打包和扫描访问信息。今天&#xff0c;我们将探索python-qrcode库&#xff0c;这是一个强大…

Golang | Leetcode Golang题解之第409题最长回文串

题目&#xff1a; 题解&#xff1a; func longestPalindrome(s string) int {mp : map[byte]int{}for i : 0; i < len(s); i {mp[s[i]]}res : 0for _, v : range mp {if v&1 1 {res v - 1} else {res v}}if res<len(s) {res}return res }

【MyBatis精讲】从入门到精通的详细指南:简化Java持久层操作的艺术

文章目录 【MyBatis精讲】从入门到精通的详细指南&#xff1a;简化Java持久层操作的艺术1.mybatis快速入门1.1创建步骤1.2mapper代理开发模式 2.mybatis增删改查2.1查询所有数据2.2 id查询数据2.3插入数据2.4修改数据2.5删除数据2.6 mybatis多条件查询2.7 mybatis动态条件查询 …

HTML标签优先级

HTML&#xff08;HyperText Markup Language&#xff09;标签的位置对于页面的结构、性能以及可维护性至关重要。合理安排标签的位置不仅有助于提高网页的加载速度&#xff0c;还能使得代码更加清晰易懂。以下是一些关于HTML标签放置的基本规则和建议&#xff1a; 1. 文档类型…

web安卓逆向之必学HTML基础知识

文章目录 HTML基础知识一、HTML的介绍1. HTML定义2. HTML 的作用1. 定义网页的结构2. 实现超文本链接3. 支持多媒体内容4. 提供表单交互5. 提高网页的可访问性和 SEO 3. 小结 二、html的基本结构1. HTML 基本结构2. HTML 基本结构的详细介绍3. 教学案例4. 补充知识5. 小结 三、…

【网络通信基础与实践第三讲】传输层协议概述包括UDP协议和TCP协议

一、进程间的通信 通信的两端应当是两个主机中的应用进程&#xff0c;也就是说&#xff0c;端到端的通信是应用进程之间的通信 运输层有一个很重要的功能就是复用和分用&#xff0c;复用是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据&#xff0c;分用是指接…

C++前后缀分解

相关知识点 C算法与数据结构 打开打包代码的方法兼述单元测试 这个算法很容易想到&#xff0c;学习了本文后&#xff0c;可以更快得想到。 前后缀分解 分治法的一种&#xff0c;将数组和字符串&#xff0c;拆分成前缀和后缀。字符串(数组&#xff09;的前缀是字符串的前i个元…

QT模型视图结构2

文章目录 Qt 模型视图结构——模型类(二)1.基本概念1.1.模型的基本结构1.2.模型索引1.3.行号和列号1.4.父项1.5.项的角色 Qt 模型视图结构——模型类(二) ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模型存储数据&#xff0c;视图组件显示模型中的数据&#…

ChatGPT提示词-中文版(awesome-chatgpt-prompts中文版)

原是Github上110.6K星的项目&#xff1a;GitHub - f/awesome-chatgpt-prompts: This repo includes ChatGPT prompt curation to use ChatGPT better. 我翻译成了中文需要自提 我用夸克网盘分享了「Chat GPT提示词.csv」&#xff0c;点击链接即可保存。打开「夸克APP」在线查看…

Windows11 WSL2的ubuntu 22.04中拉取镜像报错

问题描述 在windows11 WSL2的ubuntu 22.04中拉取镜像报错。错误为&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting header…

深度学习的关键数据结构——张量解释

参考英文文章: https://deeplizard.com/learn/video/Csa5R12jYRghttps://deeplizard.com/learn/video/Csa5R12jYRg 什么是张量&#xff08;Tensor&#xff09; 神经网络中的输入、输出和变换都是用张量表示的&#xff0c;因此&#xff0c;神经网络编程大量使用张量。张量的概念…

【资料分析】特殊考点——拉动增长、贡献率、容斥问题

拉动增长和增量贡献率 第X产业增加值 是一个整体名称&#xff0c;例如张狗剩这是一个整体的名字 增量贡献率 部分增量/ 整体增量&#xff0c;已知增量贡献率80.6%,对应的部分增量可以求得&#xff08;现期2632&#xff0c;增长率10.3%&#xff0c;可用假设分配&#xff09;&a…