STL之priority_queue的使用及其模拟实现+仿函数

STL之priority_queue的使用及其模拟实现+仿函数

  • 1.priority_queue的介绍
  • 2.priority_queue的使用
  • 3.priority_queue的模拟实现
    • 3.1解析细节
    • 3.2仿函数
    • 3.3具体实现

1.priority_queue的介绍

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

2.priority_queue的使用

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

函数声明接口说明
priority_queue()/priority_queue(first,last)构造一个空的优先级队列
empty( )检测优先级队列是否为空,是返回true,否则返回false
top( )返回优先级队列中最大(最小元素),即堆顶元素
push(x)在优先级队列中插入元素x
pop()删除优先级队列中最大(最小)元素,即堆顶元素

【注意】

  1. 默认情况下,priority_queue是大堆
  2. 如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供> 或者< 的重载。
#include <vector>
#include <queue>
#include <functional> // greater算法的头文件
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.top() << endl;// 如果要创建小堆,将第三个模板参数换成greater比较方式priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());cout << q2.top() << endl;
}

3.priority_queue的模拟实现

3.1解析细节

  • 回顾一下我们之前学习二叉树的时候,当时我们实现了向上调整和向下调整,这两个都可以实现堆排序。
  • 当我们要插入一个数据的时候是头插还是尾插呢?因为priority_queue的底层是堆,也就是二叉树,但是这个二叉树的物理结构是数组,逻辑上是二叉树,所以如果我们选择头插的话就会打乱原来的二叉树结构,导致父子变兄弟,兄弟变叔侄。所以这里我们要选择尾插,同时还要保持priority_queue的特性,在每次插入一个数据的时候还用进行向上调整。
  • 但我们要删除一个数据的时候,因为priority_queue是个优先级队列肯定是删除最大/最小的,也就是堆顶的数据,也就是头删,那我们可以直接进行头删吗?显然是不能的,因为这样做同样也会导致原来的二叉树结构,从而导致父子变兄弟,兄弟变叔侄。所以这里的办法是讲头上的数据与尾上的数据进行交换后在进行尾删最后在进行向上调整。
  • 以上是我们回顾数据结构二叉树阶段学习的知识点,如果还有不懂的地方可以翻阅前期二叉树讲解部分,在哪里有系统的讲解。

3.2仿函数

  • 在我们实现向上调整/向下调整的时候我们只能进行单一的>或者<的比较,也就是实现一种方案,但是如果我们想实现升序和降序的时候就要写两份,并且分开调用,这个办法明显比较挫。
  • 我们在C语言阶段通常用到的是回调函数,但是这个办法的缺点就是调用的时候比较麻烦,实现起来也比较麻烦。
void adjust_up(int child)
{int faster = (child - 1) / 2;while (child > 0){if (_con[child] > _con[faster]){std::swap(_con[child], _con[faster]);child = faster;faster = (child - 1) / 2;}else{break;}}
}void adjust_down(int faster)
{int child = faster * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child + 1] > _con[child]){child++;}if (_con[child]>_con[faster]){std::swap(_con[faster], _con[child]);faster = child;child = faster * 2 + 1; }else{break;}}
}
  • 所以在C++中引入了仿函数的概念
    所谓仿函数简单点说就是一个重载了()的一个函数。
    使用起来跟调用函数很像,但又不是函数,所以叫做仿函数
class fun
{
public:bool operator()(in x, int y){return x > y;}	
};fun f
cout << f(1, 2) << endl;//这个样子看起来很像是一个函数调用实际上是:f.operator()(1, 2)这样调用的。

3.3具体实现

#pragma once
#include <vector>
namespace qfw
{template<class T>class less{public:bool operator()(T x, T y){return x > y;}};template<class T>class greater{public:bool operator()(T x, T y){return x < y;}};template <class T, class Container = vector<T>, class Comper = less<T>>class priority_queue{public:void adjust_up(int child){int faster = (child - 1) / 2;while (child > 0){if (_cmp(_con[child] , _con[faster])){std::swap(_con[child], _con[faster]);child = faster;faster = (child - 1) / 2;}else{break;}}}void adjust_down(int faster){int child = faster * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _cmp(_con[child + 1] , _con[child])){child++;}if (_cmp(_con[child],_con[faster])){std::swap(_con[faster], _con[child]);faster = child;child = faster * 2 + 1; }else{break;}}}priority_queue()//这里要有个空的默认构造,原因是下面构造了一个priority_queue(InputIterator first, InputIterator last)有参构造//但是当实例化对象的时候,没有传参数的时候据选哟调用默认构造,但是类的特点就是如果定义了有参构造就不会//使用系统给的默认构造,所以这里要自己写一个默认构造。{}template <class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){push(*first);++first;}}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(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;Comper _cmp;};
}

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

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

相关文章

springboot/ssm学生请假管理系统 高校请假审批管理系统Java系统

springboot/ssm学生请假管理系统 高校请假审批管理系统Java系统 开发语言&#xff1a;Java 框架&#xff1a;springboot&#xff08;可改ssm&#xff09; vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5…

C语言:整形存储

#include<stdio.h> int main() {char a -1;signed char b -1;unsigned char c -1;printf("a%d,b%d,c%d", a, b, c);return 0; } b与a都是有符号数结果一样。a的signed相当于省略了。 运行结果 整形提升&#xff1a;整形算术运算总是以至少以缺省整型类型的精…

Hive正则表达式

Hive版本&#xff1a;hive-3.1.2 一、Hive的正则表达式概述 正则表达式是一种用于匹配和操作文本的强大工具&#xff0c;它是由一系列字符和特殊字符组成的模式&#xff0c;用于描述要匹配的文本模式。 Hive的正则表达式灵活使用解决HQL开发过程中的很多问题&#xff0c;本篇文…

AI-数学-高中-25-三角函数一三角函数对称性

原作者视频&#xff1a;【三角函数】【考点精华】3三角函数对称性&#xff08;重要&#xff09;&#xff08;中档&#xff09;_哔哩哔哩_bilibili 1.一个对称点\直线思路&#xff1a; 2.关于两点或两直线对称&#xff1a; 3.两个对称&#xff1a;一个关于点对称、一个关于直线…

数学实验第三版(主编:李继成 赵小艳)课后练习答案(八)(3)

实验八&#xff1a;近似计算 练习三 1. 按要求完成下面的任务&#xff1a; (1)求出函数 处的泰勒展开式&#xff0c;由此计算无理数e的近似值&#xff1b; clc;clear; f(x)exp(-x^2); syms x yf(x); y1matlabFunction(taylor(y,order,20)); 1/y1(1)ans 2.718283693893450 …

MYSQL performance schema详解

文章目录 MYSQL performance schema详解0、performance_schema的介绍1、performance schema入门2、performance_schema表的分类3、performance_schema的简单配置与使用4、常用配置项的参数说明5、重要配置表的相关说明6、performance_schema实践操作MYSQL performance schema详…

智能时代:创新创业的新机遇与挑战

智能时代为创新创业提供了广阔的空间和无限的可能性。以下是一些可能适合智能时代背景的创新创业方向&#xff1a; 人工智能技术应用&#xff1a;人工智能技术是当前科技领域最热门的技术之一&#xff0c;其应用范围不断扩大。创业者可以将人工智能技术应用于各个领域&#xf…

libgflags.a(gflags.cc.o): relocation R_AARCH64_ADR_PREL_PG_HI21

这个问题的解决废了好大功夫&#xff0c;最后google很多论坛才找到方法&#xff0c;特此记录&#xff0c;给大家节省时间 完整版本报错&#xff1a; /usr/bin/ld: /usr/local/lib/libgflags.a(gflags.cc.o): relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol _ZN22gfla…

Android java基础_类的封装

一.面向对象编程的引入 写一个简单的程序输出张三&#xff0c;李四的名字 class Person {String name;String getName() {return "guangdong "name;} };public class Oop {public static void main(String args[]) {Person p1 new Person();p1.name "zhangs…

让Python遇上Office--从编程入门到自动化办公实践

最近仔细的学习了这本《让Python遇上Office》的书&#xff0c;同时把我的学习进程与心得录制了同步视频。 到今天终于把全部90集完成&#xff0c;并且上传到下面的视频平台了&#xff0c;欢迎大家观看并指正&#xff01; 西瓜视频&#xff1a;https://www.ixigua.com/7300628…

洛谷p4391 无限传输

考察字符串周期的题 题目链接 结论 要求字串 s s s的最短循环字串长就是&#xff1a; a n s n − p m t [ n ] ansn-pmt[n] ansn−pmt[n] 证明如下&#xff1a; 这是最大的前缀和后缀 现在我们做如下操作&#xff1a; 补全字段 a a a和字段 b b b&#xff0c;按子段 a a a的…

【数据结构】二叉树的顺序结构及链式结构

目录 1.树的概念及结构 1.1树的概念 1.2树的相关概念 ​编辑 1.3树的表示 1.4树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2.二叉树概念及结构 2.1二叉树的概念 2.2现实中的二叉树 ​编辑 2.3特殊的二叉树 2.4二叉树的性质 2.5二叉树的存储结…

从信息隐藏到功能隐藏

本文主要记录复旦大学张新鹏教授于2022年12月在第三届CSIG中国媒体取证与安全大会上的汇报

假期刷题打卡--Day29

1、MT1224棋盘 求一个N*N棋盘中的方块总数。 格式 输入格式&#xff1a; 输入整型N 输出格式&#xff1a; 输出整型 样例 1 输入&#xff1a; 2输出&#xff1a; 5备注 考虑到取值范围&#xff0c;可用long整型定义变量 分析过程 这个题目的意思是&#xff0c;在这…

Docker 容器网络:C++ 客户端 — 服务器应用程序。

一、说明 在下面的文章中&#xff0c; 将向您概述 docker 容器之间的通信。docker 通信的验证将通过运行 C 客户端-服务器应用程序和标准“ping”命令来执行。将构建并运行两个单独的 Docker 映像。 由于我会关注 docker 网络方面&#xff0c;因此不会提供 C 详细信息。…

【Linux】学习-进程信号

进程信号 信号入门 生活角度的信号 你在网上买了很多件商品,再等待不同商品快递的到来。但即便快递没有到来,你也知道快递来临时,你该怎么处理快递。也就是你能“识别快递”,也就是你意识里是知道如果这时候快递员送来了你的包裹,你知道该如何处理这些包裹当快递员到了你…

[C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改

问题描述 WPF中DataGrid的选中行或选中者单元格&#xff0c;在焦点失去后&#xff0c;颜色会很淡&#xff0c;很不明显&#xff0c;不容易区分。 解决方法 在失去焦点的情况下&#xff0c;如何设置行或单元格与选中的时候颜色一样&#xff1f; <DataGrid.Resources>&…

华为问界M9:领跑未来智能交通的自动驾驶黑科技

华为问界M9是一款高端电动汽车&#xff0c;其自动驾驶技术是该车型的重要卖点之一。华为在问界M9上采用了多种传感器和高级算法&#xff0c;实现了在不同场景下的自动驾驶功能&#xff0c;包括自动泊车、自适应巡航、车道保持、自动变道等。 华为问界M9的自动驾驶技术惊艳之处…

第206篇| 新年有趣的产品发现;所谓正确的价值观

这是2024年一月份flomo和notion 上聚合的系列文章之&#xff08;02&#xff09;&#xff1b; 具体方法用的是这个 &#xff1a; 【知识沙虫&#xff0c;一个简单易用的知识体系建模工具】https://mp.weixin.qq.com/s/V2Cdq-1PbMQYvpE4o9NLpQ 首先&#xff0c;方法用下来还是很…

python 与 图

文章目录 图的定义1. 邻接列表2. 邻接矩阵 图的访问1. 邻接列表2. 邻接矩阵 图的定义 在 Python 中&#xff0c;可以使用字典来表示图。字典的键表示图中的顶点&#xff0c;而对应的值是与该顶点直接相连的顶点及其边的信息。 通常有两种方式来表示图&#xff1a; 邻接列表&a…