优先级队列(堆二叉树)底层的实现:

我们继续来看我们的优先级队列:

优先级队列我们说过,他也是一个容器适配器,要依赖我们的容器来存储数据;

他的第二个参数就是我们的容器,这个容器的默认的缺省值是vector,然后他的第三个参数,我们上节讲到,他的top和pop接口都是按照优先级的顺序来进行去取的,然后我们的优先级顺序默认的是大的优先级比较高,这里有一个比较坑的点,那就是我们如果想让大的数据优先级高的话,我们可以直接不传,他的默认的缺省值就是大的优先级高,这个缺省值就是less,然后我们如果想让小的数据的优先级高的话,我们就传greater,是的,这里就是刚好相反的。

优先级队列的实现:

我们来实现我们的优先级队列的底层,我们看这个push函数,我们的库里面的插入函数就是push,我们在这里的名字就是push,这个函数表示的其实还是尾插,我们的容器vector里面也是实现了push_back() 函数接口的,我们直接调用;

我们看我们的插入函数的参数,我们这里还是使用了引用来进行,这个东西我们已经说过很多次了。

因为我们不能确定这个模板T到底是什么类型的,他可能是内置类型的,比如int,也可能是其他的自定义的类型,如果是自定义的类型的话,我们的传值调用就要调用拷贝构造了,如果我们的自定义类型有动态开辟的内存的时候,我们调用拷贝构造就要给这个临时的变量开辟一段内存空间,深拷贝就比较麻烦。我们这里就选择传引用来进行,就不需要调用拷贝构造了。

我们来接着看:

由于堆具有高效维护最大或最小元素的特性,它是实现优先级队列的一种非常合适的数据结构。

我们的堆删除数据也是删除栈顶的数据,优先级最高的进行删除。(优先级队列也是先删除优先级高的)。

优先级队列的实现都是基于堆的。(我们的这个优先级队列就是我们的堆二叉树);

push函数的实现:

Adjustup函数的实现:

当我们的优先级队列(堆)入数据的时候,这个数据的插入有可能会破坏我们的优先级队列(堆)自身的结构,如果插入数据以后,我们的大堆的结构被改变,我们就要进行向上调整。

上面的这个数据的插入没有改变我们的堆的类型,他还是大堆,我们就不进行调整了;

当我们再给他插入一个数据的时候,我们这时候的大堆就不成型了,我们就要进行调整,我们把插入的数据找出来,然后我们求出他的parent结点,然后比较大小,如果child比parent大的时候,我们就交换数据,然后不断比较:

为什么我们要实现向上调整呢?

一般我们入数据的时候,我们就会用到向上调整。

我们看我们的push函数:

我们插入一个数据以后,我们一般都是插入到最后一个位置,然后我们对这个位置进行向上调整。

我们这里是size()-1,因为我们的堆二叉树,我们的第一个数据是从下标0开始的。

pop函数的实现:

我们实现我们的删除函数,想一下我们之前实现堆的时候的删除数据是怎么删除的:

我们交换堆顶和最后一个数据,然后把最后一个数据删除。这时候我们进行一个向下调整,这时候除了第一个堆顶的数据,其他的位置的数据都是有序的满足堆的要求。(这个也刚好满足向下调整的算法的条件)。

然后左右两个堆都是有序的,我们就比较现在堆顶(10)的左右孩子,因为是大堆,我们就选出比较大的数据,然后我们的堆顶和这个位置进行交换。当然,比较完后我们的这棵发生交换的子树还要和下面的孩子进行比较,直到最后合适。        

Adjustdown向下调整的实现:

pop函数:

我们的向下调整的前体就是我们是pop数据的时候,我们会需要这个。

综上所述:

向上调整的前提是向堆中插入新元素,向下调整的前提是从堆中删除堆顶元素。

仿函数:

我们的仿函数是一个类

在 C++ 里,仿函数是重载了函数调用运算符 () 的类或结构体的对象。这意味着这些对象能够像函数一样被调用。

这个就是我们的仿函数,重载了()。

这个类的对象可以像函数一样的去使用,这个类就是我们的仿函数。

我们来看一个仿函数:

我们在我们的优先级队列里面的时候,我们的模板参数的第三个参数就是我们的仿函数,我们的仿函数也是一个类:

这个就是我们的仿函数。  这个是less,我们重载的 () 是小于的类型。

这个是我们的greater,我们重载的 () 是大于的类型。

我们这里实现的和我们的库里面的有所不同,我们的库里面的,和我们的这里的相反,库里面的gerater表示小于,less表示大于。

然后当我们的这个大模板下的函数想要使用比较的时候,我们就可以使用仿函数,我们看下面的向下调整的方法,我们里面的条件比较如果是小于的话,我们就可以直接调用仿函数,看他是不是满足小于的,如果是满足小于的,返回1,我们的if条件成立。

当然,使用的前提也是,我们要先使用这个类来实例化出一个对象。

我们的compare是我们的仿函数,我们实例化出一个对象com,然后我们的这个类的对象我们可以直接的当作一个函数去使用。

我们这里调用仿函数可以是实例化出一个对象然后我们调用,这个有名调用是可以的,我们也可以是进行匿名调用。

上面的就是有名调用,匿名调用的话,我们就不实例化出对象,然后把图中的com替换成less<int>。

我们接着看:

我们看这个,我们说我们push的话,我们可以传有名对象,也可以传匿名对象,我们也可以像我们的图片中的样子,我们传我们要初始化的值,进行一个隐式类型转换,也会生成一个匿名对象。和我们的上面的屏蔽的那个匿名对象的效果是一样的。

我们接着来看我们的仿函数:

我们看一下这个代码,我们的这个优先级队列,我们的第一个参数为我们的日期类的地址,然后后面的两个参数不传,我们的第二个参数的缺省值为vector,第三个参数缺省值为less,然后我们进行打印,但是打印出来的结果不是我们想要的结果。

我们这次的模板T不是int,是我们的日期类的指针,我们进行push尾插,然后我们的new的返回值是我们的开辟的内存的指针,我们把指针插入到我们的数组里面,然后比较的时候,我们比较的就是我们的地址,我们的new开辟的内存的地址是随机的,所以我们在这里比较出来的结果就是无意义的。

那怎么办呢?

我们就可以利用我们的仿函数,我们这里的优先级队列我们的第三个仿函数我们是没有传的,所以这时候我们的里面就是缺省值less,这样的结果就是比较地址的大小,但是我们可以修改我们的仿函数,我们这里的仿函数是不期望使用指针来进行比较的,我们期望的是使用指针解引用后的数据来比较。

之前我们的仿函数:

我们就设置一个新的仿函数来解决我们的问题:

这时候得到的就是我们要的;(按照里面的数据来进行比较)。

还有:

我们看这个代码,这个代码我们的优先级队列传过去的容器是string,然后我们的后面的两个函数参数都是缺省值,我们的最后一个参数仿函数就是less。

我们然后尾插三个字符串,然后不断的取然后pop,这个就是最后的结果,这个就是按照他的大小进行排列的。

但是我们现在不想按照顺序的给他进行排列了,我们想按照每个字符串的长度来进行排列;

我们这时候就可以使用仿函数来调整我们的比较逻辑;

我们看,我们自己来实现一个仿函数,来满足我们的要求,我们比较两个string的长度。

如果默认的函数不符合我们的逻辑,我们就自己来实现一个仿函数。

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

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

相关文章

GIC驱动程序分析

今天呢&#xff0c;我们就来具体的讲一下GIC的驱动源码啦&#xff0c;这个才是重点来着&#xff0c;我们来看看&#xff1a; GIC中的重要函数和结构体&#xff1a; 沿着中断的处理流程&#xff0c;GIC涉及这4个重要部分&#xff1a; CPU从异常向量表中调用handle_arch_irq&am…

java操作redis库,开箱即用

application.yml spring:application:name: demo#Redis相关配置redis:data:# 地址host: localhost# 端口&#xff0c;默认为6379port: 6379# 数据库索引database: 0# 密码password:# 连接超时时间timeout: 10slettuce:pool:# 连接池中的最小空闲连接min-idle: 0# 连接池中的最…

Cribl 通过Splunk search collector 来收集数据

今天利用Spliunk search collector 来收集数据啦:还是要先cribl 的官方文档: Splunk Search Collector | Cribl Docs Splunk Search Collector Cribl Stream supports collecting search results from Splunk queries. The queries can be both simple and complex, as well a…

What Was the “Game Genie“ Cheat Device, and How Did It Work?

什么是“Game Genie”作弊装置&#xff0c;它是如何工作的&#xff1f; First released in 1991, the Game Genie let players enter special codes that made video games easier or unlocked other functions. Nintendo didnt like it, but many gamers loved it. Heres wha…

位运算题目:连接连续二进制数字

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;连接连续二进制数字 出处&#xff1a;1680. 连接连续二进制数字 难度 5 级 题目描述 要求 给定一个整数 n \texttt{n} n&#xff0c;将 1 \text…

第十六届蓝桥杯Java b组(试题C:电池分组)

问题描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 样例输入&#xff1a; 2 3 1 2 3 4 1 2 3 4 样例输出: YES NO 说明/提示 评测用例规模与约定 对于 30% 的评测用例&#xff0c;1≤T≤10&#xff0c;2≤N≤100&#xff0c;1≤Ai​≤10^3。对于 100…

63. 评论日记

2025年4月14日18:53:30 雷军这次是真的累了_哔哩哔哩_bilibili

电商中的订单支付(内网穿透)

支付页面 接口文档 Operation(summary"获取订单信息") GetMapping("auth/{orderId}") public Reuslt<OrderInfo> getOrderInfo(Parameter(name"orderId",description"订单id",requiredtrue) PathVaariable Long orderId){OrderI…

MySQL表的使用(4)

首先回顾一下之前所学的增删查改&#xff0c;这些覆盖了平时使用的80% 我们上节课中学习到了MySQL的约束 其中Primary key 是主键约束&#xff0c;我们今天要学习的是外键约束 插入一个表 外键约束 父表 子表 这条记录中classid为5时候&#xff0c;不能插入&#xff1b; 删除…

Kotlin作用域函数

在 Kotlin 中&#xff0c;.apply 是一个 作用域函数&#xff08;Scope Function&#xff09;&#xff0c;它允许你在一个对象的上下文中执行代码块&#xff0c;并返回该对象本身。它的设计目的是为了 对象初始化 或 链式调用 时保持代码的简洁性和可读性。 // 不使用 apply va…

C#集合List<T>与HashSet<T>的区别

在C#中&#xff0c;List和HashSet都是用于存储元素的集合&#xff0c;但它们在内部实现、用途、性能特性以及使用场景上存在一些关键区别。 内部实现 List&#xff1a;基于数组实现的&#xff0c;可以包含重复的元素&#xff0c;并且元素是按照添加的顺序存储的。 HashSet&…

Python 实现的运筹优化系统数学建模详解(最大最小化模型)

一、引言 在数学建模的实际应用里&#xff0c;最大最小化模型是一种极为关键的优化模型。它的核心目标是找出一组决策变量&#xff0c;让多个目标函数值里的最大值尽可能小。该模型在诸多领域&#xff0c;如资源分配、选址规划等&#xff0c;都有广泛的应用。本文将深入剖析最大…

数据库的种类及常见类型

一&#xff0c;数据库的种类 最常见的数据库类型分为两种&#xff0c;关系型数据库和非关系型数据库。 二&#xff0c;关系型数据库介绍 生产环境主流的关系型数据库有 Oracle、SQL Server、MySQL/MariaDB等。 关系型数据库在存储数据时实际就是采用的一张二维表&#xff0…

PE文件(十五)绑定导入表

我们在分析Windows自带的一些程序时&#xff0c;常常发现有的程序&#xff0c;如notepad&#xff0c;他的IAT表在文件加载内存前已经完成绑定&#xff0c;存储了函数的地址。这样做可以使得程序是无需修改IAT表而直接启动&#xff0c;这时程序启动速度变快。但这种方式只适用于…

计算机网络分层模型:架构与原理

前言 计算机网络通过不同的层次结构来实现通信和数据传输&#xff0c;这种分层设计不仅使得网络更加模块化和灵活&#xff0c;也使得不同类型的通信能够顺利进行。在网络协议和通信体系中&#xff0c;最广为人知的分层模型有 OSI模型 和 TCP/IP模型。这两种模型分别定义了计算…

Ollama模型显存管理机制解析与Flask部署方案对比

一、Ollama显存释放机制 Ollama部署模型后&#xff0c;显存占用分为两种情况&#xff1a; 首次调用后短暂闲置&#xff08;约5分钟内&#xff09;&#xff1a; • 释放KV Cache等中间计算数据&#xff08;约回收30%-50%显存&#xff09;。 • 模型权重仍保留在显存中&#xf…

KWDB创作者计划—KWDB技术重构:重新定义数据与知识的神经符号革命

引言&#xff1a;数据洪流中的范式危机 在AI算力突破千卡集群、大模型参数量级迈向万亿的时代&#xff0c;传统数据库系统正面临前所未有的范式危机。当GPT-4展现出跨领域推理能力&#xff0c;AlphaFold3突破蛋白质预测精度时&#xff0c;数据存储系统却仍在沿用基于关系代数的…

Unified Modeling Language,统一建模语言

UML&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;是一种标准化的图形化建模语言&#xff0c;用于可视化、规范和文档化软件系统的设计。UML 提供了一套通用的符号和规则&#xff0c;帮助开发者、架构师和团队成员更好地理解和沟通软件系统的结构…

IO模式精讲总结

一、IO模型概述 Java中的IO模型主要分为BIO&#xff08;同步阻塞IO&#xff09;、NIO&#xff08;同步非阻塞IO&#xff09;和AIO&#xff08;异步非阻塞IO&#xff09;三种。它们分别适用于不同的业务场景&#xff0c;理解其核心机制对高性能网络编程至关重要。 二、BIO&…

使用pybind11开发c++扩展模块输出到控制台的中文信息显示乱码的问题

使用pybind11开发供Python项目使用的C++扩展模块时,如果在扩展模块的C++代码中向控制台输出的信息中包含中文,python程序的控制台很容易出现乱码。以如下C++扩展框架代码为例(这是对上一篇文章简明使用pybind11开发pythonc+扩展模块教程-CSDN博客中的C++扩展框架代码进行少量…