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

面试之快速学习STL-容器适配器

1. 容器适配器

简单的理解容器适配器,其就是将不适用的序列式容器(包括 vector、deque 和 list)变得适用。
在这里插入图片描述

注意:默认使用的基础容器不代表一定只能用它,比如queue可以用deque,list。

如果你希望你的queue是list那么可以如下创建:

std::queue<int , std::list<int>> q;

可以直接通过 queue 容器适配器来初始化另一个 queue 容器适配器,只要它们存储的元素类型以及底层采用的基础容器类型相同即可。例如:

std::deque<int> values{1,2,3};
std::queue<int> my_queue1(values);
std::queue<int> my_queue(my_queue1);
//或者使用
//std::queue<int> my_queue = my_queue1;

2. priority_queue容器适配器详解

  1. priority_queue 容器适配器模拟的也是队列这种存储结构,即使用此容器适配器存储元素只能“从一端进(称为队尾),从另一端出(称为队头)”,且每次只能访问 priority_queue 中位于队头的元素。
  2. 但是,priority_queue 容器适配器中元素的存和取,遵循的并不是 “First in,First out”(先入先出)原则,而是“First in,Largest out”原则。直白的翻译,指的就是先进队列的元素并不一定先出队列,而是优先级最大的元素最先出队列
  3. priority_queue 容器适配器中存储的元素,优先级是如何评定的呢?很简单,每个 priority_queue 容器适配器在创建时,都制定了一种排序规则。根据此规则,该容器适配器中存储的元素就有了优先级高低之分。
  4. 假设当前有一个 priority_queue 容器适配器,其制定的排序规则是按照元素值从大到小进行排序。根据此规则,自然是 priority_queue 中值最大的元素的优先级最高。
  5. priority_queue 容器适配器为了保证每次从队头移除的都是当前优先级最高的元素,每当有新元素进入,它都会根据既定的排序规则找到优先级最高的元素,并将其移动到队列的队头;同样,当 priority_queue 从队头移除出一个元素之后,它也会再找到当前优先级最高的元素,并将其移动到队头。
template <typename T, typename Container=std::vector<T>, typename Compare=std::less<T> >
class priority_queue {
//......
}
  1. 可以看到,priority_queue 容器适配器模板类最多可以传入 3 个参数,它们各自的含义如下:
  • typename T:指定存储元素的具体类型;
  • typename Container:指定 priority_queue 底层使用的基础容器,默认使用 vector 容器。
  • typename Compare:指定容器中评定元素优先级所遵循的排序规则,默认使用std::less 按照元素值从大到小进行排序,还可以使用std::greater按照元素值从小到大排序,但更多情况下是使用自定义的排序规则。
  1. 作为 priority_queue 容器适配器的底层容器,其必须包含 empty()、size()、front()、push_back()、pop_back() 这几个成员函数,STL 序列式容器中只有 vector 和 deque 容器符合条件。

创建priority_queue

//以使用普通数组或其它容器中指定范围内的数据,对 priority_queue 容器适配器进行初始化:
int values[]{4,1,3,2};
std::priority_queue<int> copy_values(values, values+4); // 4,3,2,1//使用序列式容器
std::vector<int> vec{1,5,3,4,2}
std::priority_queue<int> pq(vec.begin(), vec.end()); // 5,4,3,2,1
  1. 用来初始化的数组或容器中的数据不需要有序,priority_queue 会自动对它们进行排序。
//还可以手动指定 priority_queue 使用的底层容器以及排序规则,比如std::vector<int> vec{1,5,3,4,2};
std::priority_queue<int, std::vector<int>, std::greater<int>> pq(vec.begin(), vec.end()); 
  1. 注意不支持
std::priority_queue<int, std::vector<int>, std::greater<int>> pq1{2,3,4,1,5};

在这里插入图片描述

  1. 和 queue 一样,priority_queue 也没有迭代器,因此访问元素的唯一方式是遍历容器,通过不断移除访问过的元素,去访问下一个元素。
    std::vector<int> vec1{1,5,3,4,2};std::priority_queue<int, std::vector<int>, std::greater<int>> pq(vec1.begin(), vec1.end());while (!pq.empty()) {std::cout<< pq.top()<<std::endl;pq.pop();}/*12345*/

自定义比较函数-仿函数

  1. greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数,其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了),所以调用的是fun()?
//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;
  1. 如果自己想模拟less和greater,那么使用的方法应该是这样:
    std::priority_queue<int,std::vector<int>, myFun> pq3(vec1.begin(), vec1.end());while (!pq3.empty()) {std::cout<< pq3.top()<<std::endl;pq3.pop();}/*12345*/

自定义比较函数-重载运算符

  1. 如果是个自定义类,也可以在自定义类里面自己重载运算符
    std::priority_queue<tmp1> qp2;tmp1 t1{2};tmp1 t11{3};tmp1 t111{1};tmp1 t1111{4};qp2.push(t1);qp2.push(t11);qp2.push(t111);qp2.push(t1111);while (!qp2.empty()) {std::cout<< qp2.top().x<<std::endl;qp2.pop();}/*54321*/
std::priority_queue<tmp1> qp2;

自定义比较函数-lambda

    auto cmp = [](int a, int b) -> bool { return a < b;};std::priority_queue<int, std::vector<int>, decltype(cmp)> pq4(vec1.begin(), vec1.end(),cmp);while (!pq4.empty()) {std::cout<< pq4.top()<<std::endl;pq4.pop();}/*54321*/

补充一个比较有意思的点

前面提到的自定义比较函数-lambda, 其实传入的是一个函数指针,什么意思呢?

你可以这样写效果是一样的:

    auto cmp = [](int a, int b)-> bool { return a < b; };std::priority_queue<int, std::vector<int>, std::function<bool(int,int)>> pq5(vec1.begin(), vec1.end(),  cmp);while (!pq5.empty()) {std::cout<< pq5.top()<<std::endl;pq5.pop();}

但是你不可以这样写:

    std::priority_queue<int, std::vector<int>, decltype(cmp(1,2))> pq4(vec1.begin(), vec1.end(),cmp);
//decltype(cmp(1,2))的到的是bool,而不是函数指针

小问题,好吧,是我理解的不够。

关于priority_queue的底层实现

本来准备单独用一章写,但是看了一下,其实底层实现就是一个堆,特点:

  1. heap是一颗完全二叉树:整颗树除了最底层,都是填满的,而且底层节点从左到右不存在空隙。
    在这里插入图片描述
  2. 两个操作
    • push_heap: 因为要满足完全二叉树的性质,需要将新节点放置在底层节点的最后面,也就是vector的end(),然后执行上溯操作:只要父节点比自己小,就不断调换自己和父节点的位置。
      在这里插入图片描述
    • pop_heap: 将heap的最大元素取走,也就是将根节点取走,那根据完全二叉树的性质,得把底层最后面的元素换到根节点。然后不断执行下溯操作:将自己和两个子节点中,较大的那个对调。

做完下溯操作后,可能还需做一次上溯操作

在这里插入图片描述
参考: https://blog.csdn.net/youaremyalllove/article/details/124043310

相关文章:

面试之快速学习STL-容器适配器

1. 容器适配器 简单的理解容器适配器&#xff0c;其就是将不适用的序列式容器&#xff08;包括 vector、deque 和 list&#xff09;变得适用。 注意&#xff1a;默认使用的基础容器不代表一定只能用它&#xff0c;比如queue可以用deque&#xff0c;list。 如果你希望你的qu…...

性能比较 - Spring Boot 应用程序中的线程池与虚拟线程 (Project Loom)

本文比较了 Spring Boot 应用程序中的不同请求处理方法&#xff1a;ThreadPool、WebFlux、协程和虚拟线程 (Project Loom)。 在本文中&#xff0c;我们将简要描述并粗略比较可在 Spring Boot 应用程序中使用的各种请求处理方法的性能。 高效的请求处理在开发高性能后端…...

rust学习-打印结构体中的vec

write! 宏 将格式化后的数据写入到一个缓冲区&#xff08;buffer&#xff09;&#xff0c;而不是直接打印到标准输出或文件中。 这个缓冲区可以是字符串&#xff0c;也可以是需要写入的文件的缓冲区。 write!(writer, format_string, expr1, expr2, ...);writer 参数是一个实…...

FPGA: RS译码仿真过程

FPGA: RS译码仿真过程 在上一篇中记录了在FPGA中利用RS编码IP核完成信道编码的仿真过程&#xff0c;这篇记录利用译码IP核进行RS解码的仿真过程&#xff0c;带有程序和结果。 1. 开始准备 在进行解码的过程时&#xff0c;同时利用上一篇中的MATLAB仿真程序和编码过程&#x…...

PostgreSQL 查询数据表、视图信息

--获得指定schema范围内的所有表和视图的列表&#xff0c;可指定一个排除表前缀模式with param as (select public,iit as schema_name,db2g% as exclude_pattern),base_info as (--获得所有基表select pg_namespace.nspname as schema_name, a.relname as tbl_name ,TBL as tb…...

手撕vector容器

一、vector容器的介绍 vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素&#xff0c;但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它的大小会被容器自动处理。 总结&#xff1a;vector是一个动态…...

PyMuPDF`库实现PDF旋转功能

本文介绍了一个简单的Python应用程序&#xff0c;用于将PDF文件转换为旋转90度的PDF文件。主要用于csdn网站中导出的博客pdf是横向的&#xff0c;看起来不是很方便&#xff0c;才想到用python编制一个将pdf从横向转为纵向的功能。 功能 该PDF转换工具具有以下功能&#xff1a…...

微人事 登录问题完善

重启服务端的时候&#xff0c;发现前端页面会操作不了&#xff0c;这样后端session会失效&#xff0c;我们就需要让页面重新跳转到登录页 springsecurity配置类后端配置 前端拦截器进行拦截跳转...

【业务功能篇64】安装docker容器,在docker上安装mysql

docker教程&#xff1a; https://www.runoob.com/docker/docker-tutorial.html卸载docker 较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序&#xff0c;请卸载它们以及相关的依赖项。 yum remove docker docker-client docker-client-latest docker-co…...

MyBatis的基本概念和核心组件

MyBatis的基本概念 MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0c;将接口和 Java 的 POJOs(Pla…...

sql update执行返回0,能否判断数据不存在

答案&#xff1a;不能。 update执行返回0的情况 1、没有找到需要更新的数据&#xff0c;就是这条记录不存在 例如&#xff1a;where后面的条件是id0&#xff0c;那这条记录肯定是不存在的&#xff0c;返回结果是0 2、更新时的数据和要更新的数据完全一致时 例如&#xff1a;更…...

数据分析 | 调用Optuna库实现基于TPE的贝叶斯优化 | 以随机森林回归为例

1. Optuna库的优势 对比bayes_opt和hyperoptOptuna不仅可以衔接到PyTorch等深度学习框架上&#xff0c;还可以与sklearn-optimize结合使用&#xff0c;这也是我最喜欢的地方&#xff0c;Optuna因此特性可以被使用于各种各样的优化场景。 2. 导入必要的库及加载数据 用的是sklea…...

stm32单片机开关输入控制蜂鸣器参考代码(附PROTEUS电路图)

说明&#xff1a;这个buzzer的额定电压需要改为3V&#xff0c;否则不会叫&#xff0c;源代码几乎是完全一样的 //gpio.c文件 /* USER CODE BEGIN Header */ /********************************************************************************* file gpio.c* brief Thi…...

打印X型的图案

int main() {int n0;int i0;int j0;scanf("%d",&n);for(i0;i<n;i){for(j0;j<n;j){if(ij){printf("*");}else if((ij)n-1){printf("*");}elseprintf(" ");}printf("\n");}return 0; }...

不含数字的webshell绕过

异或操作原理 1.首先我们得了解一下异或操作的原理 在php中&#xff0c;异或操作是两个二进制数相同时&#xff0c;异或(相同)为0&#xff0c;不同为1 举个例子 A的ASCII值是65&#xff0c;对应的二进制值是0100 0001 的ASCII值是96&#xff0c;对应的二进制值是 0110 000…...

Mac上传项目源代码到GitHub的修改更新

Mac上传项目源代码到GitHub的修改更新 最近在学习把代码上传到github&#xff0c;不得不说&#xff0c;真的还挺方便 这是一个关于怎样更新项目代码的教程。 首先&#xff0c;在本地终端命令行打开至项目文件下第一步&#xff1a;查看当前的git仓库状态&#xff0c;可以使用git…...

Android6:片段和导航

创建项目Secret Message strings.xml <resources><string name"app_name">Secret Message</string><string name"welcome_text">Welcome to the Secret Message app!Use this app to encrypt a secret message.Click on the Star…...

ClickHouse AST is too big 报错问题处理记录

ClickHouse AST is too big 报错问题处理记录 问题描述问题分析解决方案1、修改系统配置2、修改业务逻辑 问题描述 项目中统计报表的查询出现 AST is too big 问题&#xff0c;报错信息如下&#xff1a; 问题分析 报错信息显示 AST is too big。 AST 表示查询语法树中的最大…...

DPDK系列之二十七DIDO

一、DIDO介绍 随着计算机技术发展&#xff0c;特别是应用技术的快速发展。应用场景对计算机的处理速度几乎已经到了疯狂的地步。说句大白话&#xff0c;再快的CPU也嫌慢。没办法&#xff0c;CPU和IO等技术基本目前都处在了瓶颈之处&#xff0c;大幅度提高&#xff0c;短时间内…...

《游戏编程模式》学习笔记(七)状态模式 State Pattern

状态模式的定义 允许对象在当内部状态改变时改变其行为&#xff0c;就好像此对象改变了自己的类一样。 举个例子 在书的示例里要求你写一个人物控制器&#xff0c;实现跳跃功能 直觉上来说&#xff0c;我们代码会这么写&#xff1a; void Heroine::handleInput(Input input…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...