【C++练级之路】【Lv.10】【STL】priority_queue类和反向迭代器的模拟实现



快乐的流畅:个人主页


个人专栏:《C语言》《数据结构世界》《进击的C++》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 一、仿函数
    • 1.1 仿函数的介绍
    • 1.2 仿函数的优势
  • 二、priority_queue
    • 2.1 push
    • 2.2 pop
    • 2.3 top
    • 2.4 size
    • 2.5 empty
  • 三、反向迭代器
    • 3.1 成员变量与默认成员函数
    • 3.2 operator*
    • 3.3 operator->
    • 3.4 operator++
    • 3.5 operator- -
    • 3.6 relational operators
  • 四、反向迭代器的适用
  • 4.1 vector
    • 4.1.1 rbegin
    • 4.1.2 rend
  • 4.2 list
    • 4.2.1 rbegin
    • 4.2.2 rend
  • 总结

一、仿函数

1.1 仿函数的介绍

仿函数,是一种特殊类型的类,它重载了()运算符,使得这个类的使用看起来像一个函数,因此它又称为函数对象

具体来说,仿函数就是将函数的特性赋予到类上,使得这个类有了类似函数的行为。

1.2 仿函数的优势

C++设计仿函数之初,其实就是想替代庞杂难懂的函数指针,将函数指针替换为简单易懂的仿函数。

这里列举两个常用的仿函数——less和greater

template<class T>
struct less
{bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
struct greater
{bool operator()(const T& x, const T& y){return x > y;}
};

二、priority_queue

细节:

  1. priority_queue也是容器适配器,默认容器使用vector
  2. 其底层数据结构是,并且默认情况为大堆
    如果不了解堆,可以先看往期【数据结构】【版本2.0】【树形深渊】——二叉树入侵
  3. 为了能方便调整大小堆,增加了仿函数的模板
template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:
private:Container _con;
};

悄悄说一句:其实容器模板和仿函数模板位置互换,才更加合理!(平时不怎么会换默认容器,但是会经常换仿函数来控制大小堆)

2.1 push

入堆

细节:

  1. 先尾插元素
  2. 再使用向上调整算法
void push(const T& x)
{_con.push_back(x);adjust_up(_con.size() - 1);
}

向上调整算法

细节:

  • 构造一个仿函数模板对象,再利用重载的()运算符进行比较(当然,也可以使用匿名对象)
void adjust_up(int child)
{Compare com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

2.2 pop

出堆

细节:

  1. 先首尾元素互换
  2. 再尾删元素
  3. 最后使用向下调整算法
void pop()
{swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);
}

向下调整算法

细节:

  • 构造一个仿函数模板对象,再利用重载的()运算符进行比较(当然,也可以使用匿名对象)
void adjust_down(int parent)
{Compare com;int 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])){swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}

2.3 top

获取堆顶元素

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

2.4 size

获取堆中有效元素个数

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

2.5 empty

判断堆是否为空

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

三、反向迭代器

其实,反向迭代器也是一种适配器,它是根据不同容器的正向迭代器,来生成对应的反向迭代器。

同时,反向迭代器追求一种对称美,rbegin()在end(),rend()在begin()。

3.1 成员变量与默认成员函数

细节:

  1. 仍然使用struct,标明公有属性
  2. 成员变量是一个正向迭代器
  3. 提供带参构造函数(其余的默认成员函数不用显式定义,浅拷贝即可)
template<class Iterator, class Ref, class Ptr>
struct __reverse_iterator
{typedef __reverse_iterator self;Iterator _cur;__reverse_iterator(Iterator it): _cur(it){}
};

3.2 operator*

细节:

  1. 迭代器先自减,再解引用返回
  2. 返回引用,为了区别普通迭代器和const迭代器
Ref operator*()
{Iterator tmp = _cur;return *--tmp;
}

3.3 operator->

细节:

  1. 直接调用operator*(),根据不同容器的数据取地址返回
  2. 返回指针,为了区别普通迭代器和const迭代器
Ptr operator->()
{return &(operator*());
}

3.4 operator++

细节:

  1. 反向迭代器的++,就是正向迭代器的- -
  2. 为了区分前置和后置,后置参数加上int(无实际意义,以示区分)
  3. 前置传引用返回,后置传值返回
self& operator++()
{--_cur;return *this;
}self operator++(int)
{Iterator tmp = _cur;--_cur;return tmp;
}

3.5 operator- -

细节:同上

self& operator--()
{++_cur;return *this;
}self operator--(int)
{Iterator tmp = _cur;++_cur;return tmp;
}

3.6 relational operators

bool operator!=(const self& s)
{return _cur != s._cur;
}bool operator==(const self& s)
{return _cur == s._cur;
}

四、反向迭代器的适用

4.1 vector

template<class T>
class vector
{
public:typedef T* iterator;typedef const T* const_iterator;typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;typedef __reverse_iterator<iterator, const T&, const T*> const_reverse_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}//...
}

4.1.1 rbegin

reverse_iterator rbegin()
{return reverse_iterator(end());
}const_reverse_iterator rbegin() const
{return const_reverse_iterator(end());
}

4.1.2 rend

reverse_iterator rend()
{return reverse_iterator(begin());
}const_reverse_iterator rend() const
{return const_reverse_iterator(begin());
}

4.2 list

template<class T>
class list
{
public:typedef __list_node<T> node;typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;typedef __reverse_iterator<iterator, const T&, const T*> const_reverse_iterator;iterator begin(){return iterator(_head->_next);}const_iterator begin() const{return const_iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);}//...
}

4.2.1 rbegin

reverse_iterator rbegin()
{return reverse_iterator(end());
}const_reverse_iterator rbegin() const
{return const_reverse_iterator(end());
}

4.2.2 rend

reverse_iterator rend()
{return reverse_iterator(begin());
}const_reverse_iterator rend() const
{return const_reverse_iterator(begin());
}

总结

这次学习了仿函数的概念和基本用法,对于升降序、大小堆等转换具有极大便利。同时实现了新的容器适配器——priority_queue(优先级队列),实际上就是堆。并且也完美实现了同为适配器的反向迭代器,至此,对于适配器有了更深一步的了解和运用。


真诚点赞,手有余香

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

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

相关文章

ChatGPT数据分析应用——同期群分析

ChatGPT数据分析应用——同期群分析 ​ 同期群分析在一定程度上属于分组分析的一个变种。顾名思义&#xff0c;同期群就是相同时期的群体&#xff0c;同期群分析就是针对相同时期的群体展开分析。接下来我们让ChatGPT解释这个方法的概念并提供相应的案例。发送如下内容给ChatG…

1.2 在卷积神经网络中,如何计算各层感受野的大小

1.2 在卷积神经网络中&#xff0c;如何计算各层感受野的大小 分析与解答&#xff1a; 在卷积神经网络中&#xff0c;由于卷积的局部连接性&#xff0c;输出特征图上的每个节点的取值&#xff0c;是由卷积核在输入特征图对应位置的局部区域内进行卷积而得到的&#xff0c;因此这…

程序环境和预处理(2)

文章目录 3.2.7 命名约定 3.3 #undef3.4 命令行定义3.5 条件编译3.6 文件包含3.6.1 头文件被包含的方式3.6.2 嵌套文件包含 4. 其他预处理指令 3.2.7 命名约定 一般来讲函数和宏的使用语法很相似&#xff0c;所以语言本身没法帮我们区分二者&#xff0c;那我们平时的一个习惯是…

Flutter开发进阶之Flutter Web加载速度优化

Flutter开发进阶之Flutter Web加载速度优化 通常使用Flutter开发的web加载速度会比较慢&#xff0c;原因是Flutter web需要加载的资源处于国外&#xff0c;以下是据此所做的相应优化。 一、FlutterWeb打包 flutter build web --web-renderer canvaskit使用新命令打包 flut…

微信小程序构建npm失败解决方式

安装完所需要的依赖后&#xff0c;在微信开发者工具菜单栏中选择&#xff1a;“工具” -> “构建 npm”&#xff0c;但是失败。 解决方法&#xff1a;修改 project.config.json 开发者工具创建的项目&#xff0c;miniprogramRoot 默认为 miniprogram&#xff0c;package.js…

大数据可视化python01

import pandas as pd import matplotlib.pyplot as plt# 设置中文改写字体 plt.rcParams[font.sans-serif] [SimHei]# 读取数据 data pd.read_csv(C:/Users/wzf/Desktop/读取数据进行数据可视化练习/实训作业练习/瓜果类单位面积产量.csv ,encoding utf-8)#输出 print(data)…

数字孪生与智慧交通的融合发展:推动交通行业数字化转型,构建智慧城市新生态

随着信息技术的快速发展和城市化进程的深入推进&#xff0c;交通行业正面临着前所未有的机遇与挑战。传统的交通管理模式已难以满足日益增长的交通需求&#xff0c;而数字化转型则成为了推动交通行业创新发展的必由之路。数字孪生技术作为一种前沿的信息技术手段&#xff0c;为…

【XR806开发板试用】SPI外设使用驱动OLED显示

XR806 SPI SPI功能引脚 阅读芯片功能引脚相关资料&#xff0c;使用硬件SPI。 https://xr806.docs.aw-ol.com/study/hard_pin/ 阅读SDK SPI使用例程在xr806\device\xradio\xr806\xr_skylark\project\example\spi 路径下 SPI自发自收测试 准备 短接开发板上的MOSI(PB04)和…

tcpdump 常用用法

简要记录下tcpdump用法 监控某个ip上的某个端口的流量 tcpdump -i enp0s25 tcp port 5432 -nn -S 各个参数作用 -i enp0s25 指定抓包的网卡是enp0s25 -nn 显示ip地址和数字端口 &#xff0c;如果只 -n 则显示ip&#xff0c;但是端口为services文件中的服务名 如果一个…

外汇市场新挑战:参与模拟交易,共赢高达15000美元奖金!

在外汇金融市场&#xff0c;以往的三年可以说是“时运多舛”的三年&#xff0c;从新冠疫情爆发&#xff0c;到互联网大厂裁员浪潮&#xff1b;从大规模通货膨胀席卷全球&#xff0c;到美联储连续基金加息&#xff1b;从俄乌战争持续白热化&#xff0c;到欧洲国家面临能源困局&a…

Linux之进程信号

目录 一、概念引入 1、生活中的信号 2、Linux中的信号 二、信号处理常见方式 三、信号的产生 1、键盘产生信号 2、系统调用接口产生信号 3、软件条件产生信号 4、硬件异常产生信号 四、信号的保存 相关概念 信号保存——三个数据结构 信号集——sigset_t 信号集操…

C++/数据结构:AVL树

目录 一、AVL树的概念 二、AVL树的实现 2.1节点定义 2.2节点插入 三、AVL树的旋转 3.1新节点插入较高左子树的左侧&#xff1a;右单旋 3.2新节点插入较高右子树的右侧&#xff1a;左单旋 3.3新节点插入较高左子树的右侧---左右&#xff1a;先左单旋再右单旋 3.4新节点插…

sheng的学习笔记-卷积神经网络经典架构-LeNet-5、AlexNet、VGGNet-16

目录&#xff1a;目录 看本文章之前&#xff0c;需要学习卷积神经网络基础&#xff0c;可参考 sheng的学习笔记-卷积神经网络-CSDN博客 目录 LeNet-5 架构图 层级解析 1、输入层&#xff08;Input layer&#xff09; 2、卷积层C1&#xff08;Convolutional layer C1&…

Vue3_2024_1天【Vue3创建和响应式,对比Vue2】

前言&#xff1a; Vue3对比Vue2版本&#xff0c;它在性能、功能、易用性和可维护性方面都有显著的提升和改进。 性能优化&#xff1a;模板编译器的优化、对Proxy的支持以及使用了更加高效的Virtual DOM算法等。这使得Vue3的打包大小减少了41%&#xff0c;初次渲染提速55%&#…

k8s 集群调度,标签,亲和性和反亲和性,污点和容忍,pod启动状态 排错详解

目录 pod启动创建过程 kubelet持续监听的原因 调度概念 调度约束 调度过程 优点 原理 优先级选项 示例 指定调度节点 标签基本操作 获取标签帮助 添加标签&#xff08;Add Labels&#xff09;&#xff1a; 更新标签&#xff08;Update Labels&#xff09; 删除标…

练习 1 Web EasySQL极客大挑战

CTF Week 1 EasySQL极客大挑战 BUUCTF 典中典复习 Web SQL 先尝试输入&#xff0c;找一找交互页面 check.php 尝试万能语句 a’ or true SQL注入&#xff1a;#和–的作用 get传参只能是url编码&#xff0c;注意修改编码&#xff0c;输入的字符串要改成url格式。 POST请求和…

从基础到高级:Go 语言中 Base32 编码的全面指南

从基础到高级&#xff1a;Go 语言中 Base32 编码的全面指南 引言基础知识base32 编码简介为什么选择 base32 encoding/base32 包概览包的结构和主要类型基本概念 实战教程开始使用 encoding/base32设置开发环境基本的 base32 编码示例解码示例 深入编码细节使用不同的编码表 错…

【Spring云原生】Spring官宣,干掉原生JVM,推出 Spring Native!整体提升性能!Native镜像技术在Spring中的应用

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &#x1f680; 本…

大模型之SORA技术学习

文章目录 sora的技术原理文字生成视频过程sora的技术优势量大质优的视频预训练库算力多&#xff0c;采样步骤多&#xff0c;更精细。GPT解释力更强&#xff0c;提示词(Prompt&#xff09;表现更好 使用场景参考 Sora改变AI认知方式&#xff0c;开启走向【世界模拟器】的史诗级的…

Redis在中国火爆,为何MongoDB更受欢迎国外?

一、概念 Redis Redis&#xff08;Remote Dictionary Server&#xff09;是一个使用ANSI C编写的开源、支持网络、基于内存、分布式、可选持久性的键值对存储数据库。Redis是由Salvatore Sanfilippo于2009年启动开发的&#xff0c;首个版本于同年5月发布。 MongoDB MongoDB…