【C++容器】优先级队列 仿函数 反向迭代器

优先级队列,仿函数,反向迭代器

    • 优先级队列
      • 认识优先级队列
      • 模拟实现优先级队列
    • 浅谈仿函数
      • 仿函数的大致了解
      • 仿函数的实现
    • 反向迭代器
      • 什么是反向迭代器?
      • 反向迭代器的实现
    • 结语

优先级队列

认识优先级队列

优先级队列(priority_queue)不是队列。优先级队列是一种容器适配器,与(stack),队列(queue)具有类似的功能。

先来了解一下优先级队列有哪些功能。看下图:

在这里插入图片描述

优先级队列底层是一个(默认是大堆),第二个参数默认给的是vector,不适合list,第三个参数是仿函数函数对象)。

在这里插入图片描述

模拟实现优先级队列

大部分成员函数可以通过调用vector的成员函数来实现。

#pragma oncenamespace bit {//目前建堆默认大堆,如果想建小堆怎么办?template<class T, class Container = vector<T>>class priority_queue {private://不想让别人知道这两个函数,可以设置为私有void AdjustUp(int child){//向上调整需要和兄弟比较吗?int parent = (child - 1) / 2;while (child > 0){if (_con[child] > _con[parent]){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}//向下调整删除数据调用void AdjustDown(int parent){Compare com;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child + 1] > _con[child]){++child;}if (com(_con[child], _con[parent])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}public:template<class InputIterator>priority_queue(InputIterator first, InputIterator last){//传过来的迭代器可能不是有序的,所以要排序建堆。while (first != last){push(*first);++first;}}priority_queue()//会调用vector的默认构造函数{}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}const T& top() const{return _con[0];}bool empty() const{return _con.empty();}void pop(){//为什么swap不交换swap(_con[0], _con[_con.size() - 1]);//_con.size() - 1;//为什么这个程序不执行?执行了,但是size没变,只是_con.size() - 1_con.pop_back();AdjustDown(0);}void swap(priority_queue& pq){std::swap(_con, pq._con);}size_t size() const{return _con.size();}private:Container _con;};
}

如果想建小堆,但不增加代码量的冗余,有办法吗?

浅谈仿函数

仿函数的大致了解

怎么建小堆?可以增加一个参数函数指针,这个函数来控制大堆还是小堆。但是函数指针声明比较复杂,有一些声明很长,导致通用性变差。所以,仿函数就来了。

写一个类,类中写相应的方法,这个类作为参数,那么就可以调用该类中的方法了。

仿函数(函数对象)不是函数调用,只是具有函数的功能。

如下代码是对上面代码的补充与修改

仿函数的实现

#pragma oncenamespace bit {template<class T, class Container = vector<T>, class Compare = Greater<int>>class priority_queue {private://不想让别人知道这两个函数void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[child], _con[parent])){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void AdjustDown(int parent){Compare com;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && com(_con[child + 1], _con[child])){++child;}if (com(_con[child], _con[parent])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}public:template<class InputIterator>priority_queue(InputIterator first, InputIterator last){//传过来的迭代器可能不是有序的,所以要排序建堆。while (first != last){push(*first);++first;}}priority_queue()//会调用默认的构造函数{}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}const T& top() const{return _con[0];}bool empty() const{return _con.empty();}void pop(){//为什么swap不交换swap(_con[0], _con[_con.size() - 1]);//_con.size() - 1;//为什么这个程序不执行?执行了,但是size没变,只是_con.size() - 1_con.pop_back();AdjustDown(0);}void swap(priority_queue& pq){std::swap(_con, pq._con);}size_t size() const{return _con.size();}private:Container _con;};
}
template<class T>
struct Less
{
public:bool operator()(T& x, T& y){return x > y;}
};
template<class T>
struct Greater
{
public:bool operator()(T& x, T& y){return x < y;}
};

仿函数很方便,类中写许多的函数,资源的管理性不错,参数就可以只传一个类,封装性很强,灵活性很高。

反向迭代器

什么是反向迭代器?

**反向迭代器(reverse_iterator)**就是迭代器的相反。rbegin就是end,rend就是begin。

在这里插入图片描述

图中表示的rbegin,rend就是反向迭代器。

那如何实现反向迭代器呢?

反向迭代器的实现

仔细观察上面那张图,begin与rbegin,end与rend都是对称的。

·反向迭代器初始化可以调用正向迭代器的初始化

·反向迭代器++就是正向迭代器 的–,–就是正向迭代器的++。

先来看看库里面的反向迭代器是如何实现的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

反向迭代器中有一个正向迭代器成员。++和–操作没有问题,都是调用正向迭代器的++和–函数,但是解引用(*)函数中为什么要–?

我们根据如下代码进行分析:

#include<iostream>
#include<vector>
using namespace std;int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);vector<int>::reverse_iterator rit = v.rbegin();for (rit != v.rend()){cout << *rit << " ";++rit;}cout << endl;
}

在这里插入图片描述
)rbegin 是由 end 初始化的,所以指向最后一个元素的下一个位置。所以解引用时,rbegin 要到前一个位置,返回前一个位置的元素,rbegin不变,rbegin 和 rend 相等时循环结束。

反向迭代器的实现:

//反向迭代器可以封装一个正向迭代器,各种操作可以调用正向迭代器的函数
template<class Iterator, class Ref, class Ptr>
class ReverseIterator {
private:Iterator _it;
public:typedef ReverseIterator<Iterator, Ref, Ptr> Self;ReverseIterator()//调用正向迭代器的构造函数{}ReverseIterator(const Iterator& it):_it(it)//调用正向迭代器的拷贝构造函数{}Ref operator*()//解引用指向前一个位置的元素,本身不变。{Iterator tmp = _it;return *(--tmp);}Self& operator++()//调用正向迭代器--函数{--_it;return *this;}Self& operator--()//调用正向迭代器++函数{++_it;return *this;}bool operator!=(const Self& s)//调用正向迭代器的!=函数{return _it != s._it;}
};

结语

优先级队列(priority_queue)实现较为简单,与数据结构中的堆很相似。实现优先级队列与实现栈和队列的区别是:栈和队列可以直接复用其他容器的函数,优先级队列则需要自己加一些东西进去加工,如向下调整,仿函数等。

仿函数替换成函数指针。函数指针很麻烦,写个函数声明很长,读懂也容易绕晕。仿函数就是一个类,类中可以写许多函数,封装的很好,使用时很方便。

反向迭代器(reverse_iterator)就是理解解引用(*)的过程,写起来就是封装一个正向迭代器。

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

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

相关文章

低成本打造便携式无线网络攻防学习环境

1.摘要 一直以来, 无线网络安全问题与大众的个人隐私息息相关, 例如: 为了节省流量, 连接到一个看似安全的免费WiFi, 在使用过程中泄露自己的各类密码信息甚至银行卡账号密码信息。随着家用智能电器的普及, 家中的各类智能设备连入家里的无线网络, 却突然失灵, 甚至无法正常连…

@Scheduled注解 定时任务讲解

用于在Java Spring框架中定时执行特定任务的注解 Scheduled&#xff0c;它能够指定方法在特定时间间隔或特定时间点执行。默认参数是cron&#xff0c;cron参数被用来定义一个Cron表达式&#xff0c;它代表了任务执行的时间规则 参数如下 Cron 这是是一种时间表达式&#xff…

【应用程序启动过程-三种加载控制器的方式-上午内容复习 Objective-C语言】

一、我们先来回忆一下,上午所有内容 1.首先呢,我们先说的是这个“应用程序启动过程”, 应用程序启动过程里面,有三方面内容 1)UIApplication对象介绍 2)AppDelegate对象介绍 3)应用程序启动过程 现在不知道大家对这个应用程序启动过程有印象吗, 2.首先,这个UIAp…

MySQL数据库时间计算的用法

今天给大家分享如何通过MySQL内置函数实现时间的转换和计算&#xff0c;在工作当中&#xff0c;测试人员经常需要查询数据库表的日期时间&#xff0c;但发现开发人员存入数据库表的形式都是时间戳形式&#xff0c;不利于测试人员查看&#xff0c;测试人员只能利用工具对时间戳进…

【 顺序表经典算法—移除元素和合并两个有序数组】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 经典算法OJ题1&#xff1a; 移除元素 解法一、逐个判断 解法二、双指针覆盖 经典算法OJ题2&#xff1a; 合并两个有序数组 OJ题分为两个类型&#xff1a; 总结 前言…

MAX/MSP SDK学习07:list传递

实现自定义Obejct&#xff0c;要求将传入的一组数据100后传出。 #include "ext.h" #include "ext_obex.h" typedef struct _listTrans {t_object ob;void* outLet;t_atom* fArr;long listNum;} t_listTrans;void* listTrans_new(t_symbol* s, long arg…

Bug等级划分

Bug是指在程序或系统中存在的错误、缺陷或异常&#xff0c;是由于编码错误、设计问题、逻辑错误或其他因素导致的。 常见的Bug分类方法 功能性Bug与软件的功能有关&#xff0c;软件无法正常工作、功能与需求不符或功能执行不正确。 用户界面Bug与软件的用户界面有关&#xff…

Unity中Shader双向反射分布函数BRDF

文章目录 前言一、渲染方程二、什么是BxDF1、BSSRDF2、BRDF3、BTDF4、BSDF 三、迪士尼原则的BRDF四、迪士尼原则的BRDF的参数五、在Unity中看一下默认Shader的这些参数六、在这里记录一下使用 Blender 和 SubstancePainter 的流程1、在Blender中导出模型为 .obj 格式2、在Subst…

Go 实现网络代理

使用 Go 语言开发网络代理服务可以通过以下步骤完成。这里&#xff0c;我们将使用 golang.org/x/net/proxy 包来创建一个简单的 SOCKS5 代理服务作为示例。 步骤 1. 安装 golang.org/x/net/proxy 包 使用以下命令安装 golang.org/x/net 包&#xff0c;该包包含 proxy 子包&am…

天软特色因子看板 (2023.11 第12期)

该因子看板跟踪天软特色因子A05006(近一月单笔流入流出金额之比(%)&#xff0c;该因子为近一个月单笔流入流出金额之比(%)均值因子&#xff0c;用以刻画在 市场日内分时成交中流入、流出成交金额的差异性特点&#xff0c;发掘市场主力资金的作用机制。 今日为该因子跟踪第12期&…

Windows平台Unity下实现camera场景推送RTMP|轻量级RTSP服务|实时录像

技术背景 我们在对接Unity平台camera场景采集的时候&#xff0c;除了常规的RTMP推送、录像外&#xff0c;还有一些开发者&#xff0c;需要能实现轻量级RTSP服务&#xff0c;对外提供个拉流的RTSP URL。 目前我们在Windows平台Unity下数据源可采集到以下部分&#xff1a; 采集…

@PostConstruct虽好,请勿乱用

1.问题说明 在日常的业务开发中&#xff0c;有时会利用PostConstruct在容器启动时执行一些任务。例如&#xff1a; PostConstruct public void init(){System.out.println("service 初始化..............."); }一般情况这没什么问题&#xff0c;但最近一个同事在做…

ui5使用echart

相关的代码已经发布到github上。 展示下相关的实现功能 1、柱状图-1 2、柱状图-2 3.折线图 4.饼状图 如何使用&#xff1a; 使用git clone项目到本地 git clone https://github.com/linhuang0405/com.joker.Zechart找到index.html。在vscode里右键选择Open with Live Serve…

BLE通用广播包

文章目录 1、蓝牙广播数据格式2、扫描响应数据 1、蓝牙广播数据格式 蓝牙广播包的最大长度是37个字节&#xff0c;其中设备地址占用了6个字节&#xff0c;只有31个字节是可用的。这31个可用的字节又按照一定的格式来组织&#xff0c;被分割为n个AD Structure。如下图所示&…

VS Code 如何搭建C/C++环境

目录 一、VS Code是什么&#xff1f; 二、VS Code下载和安装 2.1下载 2.2安装 2.3环境介绍 三、Vs Code配置C/C环境 3.1下载和配置MinGW-w64编译器套件 3.1.1下载 3.1.2配置 一、VS Code是什么&#xff1f; 跨平台&#xff0c;免费且开源的现代轻量级代码编辑器 Vis…

【MATLAB源码-第85期】基于farrow结构的滤波器仿真,截止频率等参数可调。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 Farrow结构是一种用于实现可变数字滤波器的方法&#xff0c;尤其适用于数字信号处理中的采样率转换和时变滤波。它通过多项式近似来实现对滤波器系数的平滑变化&#xff0c;使得滤波器具有可变的群延时或其他参数。 Farrow结…

mysql中数据是如何被用B+树查询到的

innoDB是按照页为单位读写的 那页中有很多行数据&#xff0c;是怎么执行查询的呢&#xff0c;首先我们肯定&#xff0c;是以单向列表形式存储的&#xff0c;提高了增删的效率&#xff0c;但是查询效率低。所以实际上对页中的行数据进行了优化&#xff0c;能以二分的方式进行查…

基于北方苍鹰算法优化概率神经网络PNN的分类预测 - 附代码

基于北方苍鹰算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于北方苍鹰算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于北方苍鹰优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

Java面试-框架篇-Mybatis

Java面试-框架篇-Mybatis MyBatis执行流程延迟加载使用及原理一, 二级缓存来源 MyBatis执行流程 读取MyBatis配置文件: mybatis-config.xml加载运行环境和映射文件构造会话工厂SqlSessionFactory会话工厂创建SqlSession对象(包含了执行SQL语句的所有方法)操作数据库的接口, Ex…

IP地址定位技术发展与未来趋势

随着互联网的快速发展&#xff0c;人们对网络的需求和依赖程度越来越高。在海量的网络数据传输中&#xff0c;IP地址定位技术作为网络安全与信息追踪的重要手段&#xff0c;其精准度一直备受关注。近年来&#xff0c;随着技术的不断进步&#xff0c;IP地址定位的精准度得到了显…