当前位置: 首页 > news >正文

双端队列和优先级队列

文章目录

  • 前言
  • deque
    • deque底层设计
    • 迭代器设计
  • priority
  • 仿函数
  • 数组中的第k个最大元素
  • 优先级队列模拟实现
    • push
    • pop
    • 调整
    • 仿函数
    • 存储自定义类型

前言

今天要介绍比较特殊的结构,双端队列。
还有一个适配器,优先级队列。

deque

在这里插入图片描述
栈的默认容器用了一个deque的东西,这个东西是啥?
deque虽然是队列,但它不是正队列,它是双端队列。

为什么叫双端队列,因为它最适合头插头删,尾插尾删。

deque对标的是vector+list.

它的结构和前面没有什么差别。
在这里插入图片描述

这些功能只有我们之前讲的list能做到。
在这里插入图片描述

最牛逼的是还有这个
在这里插入图片描述

看,它既支持vector的功能又支持list的功能。

但是这个东西真的这么牛吗?
要回答这个问题,我们得看一下deque的底层设计。

deque底层设计

我们先来分析一下顺序表和链表的区别。

顺序表:
它最大的优点就是空间连续随机访问,但是也带来了,头插,中间插入删除的困难。
在这里插入图片描述

其实顺序表还有一个优点就是高速缓存效率高,但是这里学习的时候不作为重点。

链表:
在这里插入图片描述

能不能把list和vector的优点合起来呢?
有人用了一个折中的思路。

折中的思路,一次开一个的小数组,满了以后在开一段空间,不扩容。
怎样管理多端小数组?中控(指针数组)
在这里插入图片描述

假设我要头插或者尾插
在这里插入图片描述

大家看这个结构什么时候需要扩容?
中控满了就需要扩容。但是扩容的代价低。因为中控扩容中只拷贝指针。

在这里插入图片描述

假设我要访问第25个数据,怎么访问?
在这里插入图片描述

小数组要不要扩容,这是很灵活的,得你自己去看

为什么它的扩容代价低?
相比vector而言,只需要拷贝指针,代价低了很多。
但相比list而言,还是比不过list,list没有扩容的概念,增加一个数据它就开一次空间。

在这里插入图片描述

注意,deque的随机访问比vector低,但是比list还是高很多。

在这里插入图片描述

deque适合干嘛?
头插头删多,尾插尾删多可以用。

大家可以去测试一下deque和vector和list sort的效率
其实效率都不如拷贝到vector,进行排序然后拷贝回去。

迭代器设计

它的迭代器设计是我们目前为止接触到最复杂的迭代器。
在这里插入图片描述
它有四个指针,看它们分别干嘛的?

在这里插入图片描述

cur:当前指向数据的位置
first和last:buff数组开始和结束
node:反向指向中控数组

在这里插入图片描述
好像也没有那么难理解。

这里就不模拟实现了,deque在现实生活中用的其实不多,除了用来做头插头删,做deque的默认容器以外,
实际当中用的还是vector和list.

如果对deque有兴趣可以去看一下源码,但其实没必要,有些东西我们需要深入学习,但deque我们只需要
了解它的框架就可以了。

priority

这个东西还是挺适用的,很多地方都要用。
在这里插入图片描述
默认容器是vector,当然你也可以传deque,但是这里deque不如vector.

它有个要求,就是随机访问的迭代器。

它是优先级队列,看一下接口就知道了。
在这里插入图片描述
它的接口跟我们的堆很想。

它这里需不需要符合先进先出?
不需要,它是要求优先级高的先出。

它也不支持遍历,容器适配器都不支持遍历。

还是出一个走一个。

void test_priority_queue()
{
//默认是大堆,大的优先级高priority_queue<int> pq;pq.push(1);pq.push(0);pq.push(5);pq.push(2);pq.push(1);pq.push(7);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;
}

在这里插入图片描述

它默认认为什么的优先级高?
大的优先级高。

它的底层是一个vector,vector的底层实际是一个堆,也就是一个完全二叉树。
默认是大堆。

那我现在有一个问题,以后要用topk的时候,还需要自己写一个堆出来吗?
不需要。

如果要变成小堆,怎么办?
用了一个仿函数。
在这里插入图片描述
这里用了一个less,默认是大堆。

// 小堆 -- 小的优先级高
priority_queue<int, vector<int>, greater<int>> pq;

包一下这个文件

#include <functional>

仿函数

假设我需要写一个大于或小于的仿函数,怎么写呢?
其实很简单, 仿函数都有一个特点,重载一个()的运算符。
这个()就是函数参数的括号的运算符。

在这里插入图片描述

如果但看这一行,你会觉得lessFunc是什么?

cout << lessFunc(1, 2) << endl;

函数名或者函数指针,但它其实是一个对象。
这个类叫做仿函数。表示它的对象可以像函数一样去使用。但它的本质是调用operator(), 是运算符重载。

仿函数有什么好处?
它的好处是能更好的去做类型。模拟实现优先级队列的时候能更好理解。
它的对象可以像函数一样调用,我们就可以控制很多行为。

C++搞出这个东西是由于函数指针太复杂了。具体是函数指针的类型太复杂了。有些地方是要去做回调。

C的qsort
在这里插入图片描述
C++的sort
在这里插入图片描述
把上面的仿函数更改为针对任意类型。

#include <functional>
template<class T>
struct Less
{bool operator()(const T& x, const T& y){return x < y;}
};int main()
{Less<int> lessFunc;cout << lessFunc(1, 2) << endl;return 0;
}

下面我们用优先级队列来做一个题目

数组中的第k个最大元素

数组中的第k个最大元素
在这里插入图片描述

在这里插入图片描述
返回第k个最大元素,好不好找?
排序就搞定了。
在这里插入图片描述

但是时间复杂度不满足
这道题最好的方式肯定还是快排的思想,我们这里不考虑这个,我们把堆用起来。

如果这道题优先级队列来解决,怎么解决?
在这里插入图片描述

pop k次,堆顶的元素就是我们要找的元素。
这样写,时间复杂度是多少?
第四行的时间复杂度是多少?N
我们知道向下建堆可以O(N).

pop的时间复杂是多少?
K*logN

所以合计的时间复杂度。
O(KlogN+N)
这里如果k==N,那就麻烦了,时间复杂度是N
logN

假设N远大于k,且N很大,有什么优化方式?
我们要找最大的前k个,除了全部建大堆,还有没有其他方式?

我们还可以建k个元素的堆。

那我们建大堆还是小堆?
Top k最大的前k个,我们是要建小堆。

看代码
在这里插入图片描述
这样解决时间复杂度是多少?
在这里插入图片描述

它最大的特点是消耗空间很小。

我们学会了优先级队列,根本不需要去手搓一个堆

优先级队列模拟实现

在这里插入图片描述

首先,底层要存数据还是用vector这样的东西来存.

接着我们在把要写的接口给写出来,这跟栈还是很像的。
在这里插入图片描述

push

想一想堆是怎么push数据的?
堆的底层是一个数组的结构。我们插入数据的时候向上调整。
在这里插入图片描述
在这里插入图片描述

pop

堆的数据删除怎么删?
堆的删除直接删,不然堆就挪乱了。效率极低。
堆删除数据是删除第一个数据,将第一个数据和最后一个数据交换,然后删除最后一个数据,然后从根开始向下调整。
在这里插入图片描述
在这里插入图片描述

调整

怎呢向上调整?
跟父结点比,挨着挨着往上走就可以了。
先搞大堆。
在这里插入图片描述

template<class T, class Container = vector<T>>class priority_queue{public:void adjust_up(int child){Comapre com;int parent = (child - 1) / 2;while (child > 0){if (_con[parent] < _con[child]){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjust_down(int parent){size_t child = parent * 2 + 1;while (child < _con.size()){Comapre com;if (child + 1 < _con.size() && _con[child] < _con[child + 1]){++child;}if (_con[parent] < _con[child]){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const T& x){_con.push_back(x);adjust_up(_con.size()-1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};

快速写了一个优先级队列,测试一下,自己写的代码。

在这里插入图片描述
在这里插入图片描述

它的适配器默认是vector,这里用deque,但是它照样能跑。
也就是说这里你只需要符合它的需求,满足上面的接口,这个程序都可以正常运行。

它们的底层已经天差地别了,一个是vector,一个是双端队列,但是对这个上层的优先级队列完全没有影响。这就是容器适配器,只要你那个东西满足我的需求,我就可以转换成我想要的东西。

仿函数

上面写的是大堆的代码,那我要变成小堆呢?
要变成小堆,就要控制上面调整的比较方式。
在这里插入图片描述

总不能纯手搓吧。我们肯定是先把大堆写出来,加东西,然后顺便改一下就变成小堆了。
那这一定是外部可以传一个东西去控制,它这里是通过模板参数去控制的。

怎么通过模板参数来控制呢?
先写两个可以比较的仿函数。
在这里插入图片描述
那就可以用这个类型的对象去比较。

//跟库里面保持一致,大堆用一个小于。
template<class T, class Container = vector<T>,  class Compare = less<T>>

神奇的事情发生了。
大堆和小堆就可以随意更换了。

void adjust_up(int child)
{Comapre com;int parent = (child - 1) / 2;while (child > 0){//if (_con[parent] < _con[child])if (com(_con[parent], _con[child]))//if (Comapre()(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void adjust_down(int parent)
{size_t child = parent * 2 + 1;while (child < _con.size()){Comapre com;//if (child + 1 < _con.size() //	&& _con[child] < _con[child + 1])if (child + 1 < _con.size() && com(_con[child],_con[child + 1])){++child;}//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
template<class T, class Container = vector<T>,  class Compare =less<T>>

以前用的泛型是控制数据类型,不知道具体的数据类型是什么,你传什么就是什么。
现在控制的不是类型,控制的是比较方式。默认它是less,那com就是less对象,less对象去调用operator(),那它就是小于比较方式。
在这里插入图片描述
它能够通过模板参数传类型,类型里面实例化对象控制比较的方式。

跟函数指针的比较
模板传的是类型,仿函数是一个类。类型就可以在模板参数传,模板参数传有什么好处?
我整个类都可以用。

仿函数还有其他功能,我们在后面会C++的学习中会慢慢感受到

存储自定义类型

假设我们优先级数列存储的数据不再是内置类型。自定义类型,能不能用优先级队列。
也可以。

大堆:
在这里插入图片描述
在这里插入图片描述

小堆:
在这里插入图片描述
在这里插入图片描述

日期类需要重载大于,小于才行。
如果没有重载就需要写仿函数才能搞定。
在这里插入图片描述

给大家看一下更牛逼的东西。
在这里插入图片描述

结果每次都不一样
在这里插入图片描述

怎么回事呢?
现在存进去的T是Date*,不是Date.
Date* 可以进行比较,但这不是我想要的。
Date* 是new出来的,new是堆上申请的空间,那个地址可能先大先小,完全没有规律。

template<class T, class Container = vector<T>,  class Compare =less<T>>

如果我非要这样比较呢?
我们的骚操作又要上场了。

默认是大堆。
在这里插入图片描述
在这里插入图片描述
再怎么运行他都不会变。
在这里插入图片描述

小堆:
再写一个仿函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这是不是给了一个非常大的空间
它真正的优势在于,我就是个compare对象,有个默认比较方式,但是你想要其他的比较方式,全部都可以交给你控制。你想怎么比就怎么比。

相关文章:

双端队列和优先级队列

文章目录 前言dequedeque底层设计迭代器设计 priority仿函数数组中的第k个最大元素优先级队列模拟实现pushpop调整仿函数存储自定义类型 前言 今天要介绍比较特殊的结构&#xff0c;双端队列。 还有一个适配器&#xff0c;优先级队列。 deque 栈的默认容器用了一个deque的东西…...

c#读取CSV文件跟Excel导入成DataTble

1.读取CSV文件 /// <summary>/// 读取CSV文件/// </summary>/// <param name"fileName">文件路径</param>public static DataTable ReadCSV(string fileName){DataTable dt new DataTable();FileStream fs new FileStream(fileName, FileM…...

Python编程技巧 – 单字符函数

Python编程技巧 – 单字符函数 Python Programming Skills – Single Character Function By JacksonML 0. 前言 Python有其内建(built-in)的一系列函数&#xff0c;其中&#xff0c;有两个函数为长度为一的字符设计。这样的函数是单字符函数&#xff0c;尽管它们操作的对象…...

xcode-文件

IOSDeviceSupoprt 共享缓存库 当你使用新的 iOS 设备连接到 Xcode 时&#xff0c;Xcode 会自动下载并存储相应版本的设备支持文件。 每个 iOS 版本都有一个对应的设备支持文件集&#xff0c;这些文件包含有关设备架构和操作系统的信息&#xff0c;以便 Xcode 能够正确地调试和…...

云原生之深入解析网络服务Istio、eBPF和RSocket Broker

一、服务治理 ① “服务治理”简介 在微服务时代&#xff0c;一个复杂的应用程序被分解为多个组件化、协作和连接的单元&#xff0c;服务往往会承担越来越多的业务责任&#xff0c;这使得服务治理的难度前所未有&#xff0c;仅仅依靠微服务框架级的治理是不够的&#xff0c;构…...

文件系统和磁盘调度

文件系统 概述 文件系统&#xff1a;一种用于持久性存储的系统抽象 在存储器上&#xff1a;组织、控制、导航、访问和检索数据大多数计算机包含文件系统 文件&#xff1a;文件系统中一个单元的相关数据在操作系统中的抽象 文件系统功能 分配文件磁盘空间 管理文件块管理空…...

C++ stringOJ练习题

目录 把字符串转换成整数 反转字符串 字符串中的第一个唯一字符 字符串最后一个单词的长度 找出字符串中第一个只出现一次的字符 字符串相加 字符串最后一个单词长度 字符串相乘 反转字符串3 反转字符串2 验证回文串 把字符串转换成整数 通过遍历字符串并逐位转换…...

解决问题:ImportError: cannot import name ‘_update_worker_pids‘

在复现一些较早年份文献时&#xff0c;网络架构是较早的Pytorch模型&#xff0c;现阶段的高版本不兼容&#xff0c;所以就得安装比如低版本的torch0.4.0以解决问题。 目录 一、问题1.1 问题分析 二、解决办法2.1 Pytorch安装2.2 torchvision安装2.3 测试是否安装成功 三、总结…...

【面试总结】Java面试题目总结(一)

&#xff08;以下仅为个人见解&#xff0c;如果有误&#xff0c;欢迎大家批评并指出错误&#xff0c;谢谢大家&#xff09; 1.项目中的验证码功能是如何实现的&#xff1f; 第一步&#xff1a;在项目的pom.xml文件中导入 EasyCaptcha 的依赖&#xff1b; <dependency>…...

大白话数据中台,何为数据中台

文章目录 一、数据中台二、本质三、构建数据中台的几个方面四、总结 最近一直在研发Ai平台&#xff0c;忙碌非凡。 在之余&#xff0c;有小伙伴质疑数据中台其实就是一个web系统&#xff0c;无法就是添加一些业务逻辑的增删改查。 答曰&#xff1a; 回去好好把科普下什么是数…...

escapeshellarg参数绕过和注入的问题

escapeshellcmd escapeshellcmd(string $command): string command--要转义的命令。 escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec() 或 system() 函数&#xff0c;或者 执行操作符 之前进行转义。 …...

CSS——标准流、浮动、Flex布局

1、标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如&#xff1a;块元素独占一行&#xff0c;行内元素可以一行显示多个。 2、浮动 作用&#xff1a;让块元素水平排列 属性名&#xff1a;float 属性值&#xff1a; left&#xff1a;…...

P21 类神经网络训练不起来怎么办- 自动调整学习率 Adapative learning rate

梯度大&#xff0c;学习率减小梯度小&#xff0c;学习率变大adam随时间变化 &#xff0c; decay / warm up 调整学习率方法一 adagrad 学习率除以 梯度的方差 方法二 RMSProp 目前最常用的&#xff1a; Adam: RMSProp Moment Learning rate schedule : decay/ warm up l…...

[Linformer]论文实现:Linformer: Self-Attention with Linear Complexity

文章目录 一、完整代码二、论文解读2.1 介绍2.2 Self-Attention is Low Rank2.3 模型架构2.4 结果 三、整体总结 论文&#xff1a;Linformer: Self-Attention with Linear Complexity 作者&#xff1a;Sinong Wang, Belinda Z. Li, Madian Khabsa, Han Fang, Hao Ma 时间&#…...

【Jeecg Boot 3 - 第二天】1.1、后端 docker-compose 部署 JEECGBOOT3

一、场景 二、实战 ▶ 2.1 修改配置文件 &#xff1e; 目的一&#xff1a;将 dev 变更为生产环境 prod &#xff1e; 目的二&#xff1a;方便spring项目调用docker同个network下的redis和mysql ▶ 2.2 编写dockerfile ▶ 2.3 编写docker-compose.yaml ▶ 2.4 打…...

Centos单用户模式修改root密码

在CentOS 7的单用户模式下&#xff0c;你可以按照以下步骤修改root用户密码&#xff1a; 启动CentOS 7并进入GRUB菜单。在启动时按下任意键进入GRUB菜单。 在GRUB菜单中&#xff0c;选择要启动的CentOS 7内核版本&#xff0c;并按下e键进行编辑。 找到以 ro 开头的行&#xf…...

[Unity]关于Unity接入Appsflyer并且打点支付

首先需要去官方下载Appsflyer的UnityPackage 链接在这afPackage 然后导入 导入完成 引入此段代码 using AppsFlyerSDK; using System.Collections; using System.Collections.Generic; using UnityEngine;public class AppflysManager : MonoBehaviour {public static App…...

AICore 带来了 Android 专属的 AI 能力,它要解决什么?采用什么架构思路?

前言 Google 最近发布的 Gemini 模型在全球引起了巨大反响&#xff0c;其在多模态领域的 Video demo 无比震撼。对于 Android 开发者而言&#xff0c;其中最振奋人心的消息莫过于 Gemini Nano 模型将内置到 Android 系统当中&#xff0c;并开放给开发者使用。 事实上&#xf…...

python学习1

大家好&#xff0c;这里是七七&#xff0c;今天开始又新开一个专栏&#xff0c;Python学习。这次思考了些许&#xff0c;准备用例子来学习&#xff0c;而不是只通过一大堆道理和书本来学习了。啊对&#xff0c;这次是从0开始学习&#xff0c;因此大佬不用看本文了&#xff0c;小…...

【SpringBoot】Spring Boot 单体应用升级 Spring Cloud 微服务

Spring Cloud 是在 Spring Boot 之上构建的一套微服务生态体系&#xff0c;包括服务发现、配置中心、限流降级、分布式事务、异步消息等&#xff0c;因此通过增加依赖、注解等简单的四步即可完成 Spring Boot 应用到 Spring Cloud 升级。 Spring Boot 应用升级为 Spring Cloud…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...