C++栈、队列、优先级队列模拟+仿函数
目录
一、栈的模拟和deque容器
1.deque
1.1deque结构
1.2deque优缺点
2.stack模拟
二、队列的模拟
三、priority_queue优先级队列
1.优先级队列模拟
2.添加仿函数
一、栈的模拟和deque容器
在之前,我们学过了C语言版本的栈,可以看这篇文章 栈和队列。
但是C语言没有模板,我们只能固定一个类型去写,在C++中引入了模板的概念,我们只需要写一份,在调用中给到类型,编译器会自动去帮我们推导是栈里面元素的类型,会非常方便。
1.deque
我们可以看到,库函数里面的栈调用的是一个deque容器。
deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。
1.1deque结构
首先deque有一个中控数组,这个数据是指针数组,存放的内容是指针,每个指针都指向的一块空间的起始地址。
他的迭代器有 cur(当前数据当前位置) fisrt(数据起始位置)last(数据结尾位置) node(指向数据的指针)。
头插就去找到最前面的那个有效指针进行头插,尾插就找最后面那个有效指针尾插,遍历就通过迭代器每一个空间块从头遍历到位,就换下一个空间块。
1.2deque优缺点
deque实际上是一个缝合怪,他结合了vector和list的内容,将他们糅合在了一起。
优点
与vector比较,deque的优势是 :头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。
与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。
但是他也有缺点
deque容器不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list。
那么为何他能在栈和队列中使用,并成为默认容器呢?
因为栈和队列需要尾插,尾删,队列需要尾插,头删deque容器完全可以适配这些需求,因为不需要遍历,并且deque扩容时不需要挪动数据,这也是的deque的效率变高。
2.stack模拟
stack的模拟非常简单,调用模板Container容器的函数就可以了,也不需要迭代器(不用遍历),也不需要构造函数析构函数什么的,因为Container容器是自定义类型,会自动调用的相关构造析构拷贝函数。
#pragma once
#include<deque>
namespace kky
{template<class T, class Container = deque<T>>class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}const T& top(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}
二、队列的模拟
队列模拟跟stack差不都,多了一个back接口,出数据的时候要调用pop_front()
#pragma once
#include<deque>
namespace kky
{template<class T, class Container = deque<T>>class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}const T& front(){return _con.front();}const T& back(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}
三、priority_queue优先级队列
优先级队列出数据的时候,会先出优先级高的数据。
如何来判断优先级的高低呢?
这跟你传的数据类型有关,先举个例子
我们插入了 1,10,8,5,6 但出数据的时候缺省按照数据的大小顺序来出的,在这里使用数据的大小来看段他们优先级的高低。
优先级队列出数据时会帮我们做好排序,他的本质就是堆,通过堆的向上向下调整来处理优先级问题。具体堆排序的过程可以看选择排序中的堆排序。
1.优先级队列模拟
优先级队列的模拟实现就是要建堆,每一次插入数据都要进行向上调整,保证是大堆或者小堆。
出数据的时候将第一个数据和最后一个数据互换,再进行尾删,因为第一个数据是我们想要出的数据,将他和最后一个数据交换再尾删,就可以提取出这个数据了,同时现在只有第一个元素不符合小堆或者大堆的情况,其他元素都符合,因此进行一次从索引为0位置的向下调整即可。
namespace kky
{template<class T,class Container = vector<T>>class priority_queue{public:void adjust_up(size_t child){while(child>0){size_t parent = (child - 1) / 2;if (_con[child] > _con[parent]){swap(_con[child], _con[parent]);child = parent;}else{break;}}}void adjust_down(size_t parent){int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child] < _con[child + 1]){child++;}if (_con[child] > _con[parent]){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);}T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}
刚刚的代码构建了一个大堆,但是我们如果想要构建小堆,难不成又要重写一份代码吗? 那必定不是可能的。
2.添加仿函数
在C语言中,我们可以通过函数指针来处理顺序的问题,但是函数指针类型很繁琐,并且不容易理解,C++推出了仿函数来帮助我们处理这类问题。
写一个类,仅仅重载了operator(),返回类型为bool,在后面进行判断的时候,我们就可以调用这个类对象的(),类似于函数一样,就可以处理了,
template<class T>
class Less
{
public:bool operator()(const T& x1, const T& x2){return x1 < x2;}
};
第一个方式太丑陋了,一般使用第二种方式去调用。
那之前,我们代码中的判断语句,都可以通过调用仿函数更改了
给模板参数再添加一个类
template<class T, class Container = vector<T>,class Compare = Less<T>>
现在就可以开始更改了
只需要注意顺序即可,需要这样判断的都可以更改,参考如下代码
namespace kky
{template<class T, class Container = vector<T>,class Compare = Less<T>>class priority_queue{public:void adjust_up(size_t child){Compare com;while (child > 0){size_t parent = (child - 1) / 2;if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;}else{break;}}}void adjust_down(size_t 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[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);}T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}
这是我们写的Less仿函数,如果你想让优先级队列建小堆,就可以写再写一个仿函数
template<class T>
class Greater
{
public:bool operator()(const T& x1, const T& x2){return x1 > x2;}
};
需要的时候调用一下即可
相关文章:

C++栈、队列、优先级队列模拟+仿函数
目录 一、栈的模拟和deque容器 1.deque 1.1deque结构 1.2deque优缺点 2.stack模拟 二、队列的模拟 三、priority_queue优先级队列 1.优先级队列模拟 2.添加仿函数 一、栈的模拟和deque容器 在之前,我们学过了C语言版本的栈,可以看这篇文章 栈和…...

ES挂载不上怎么处理?
全文搜索 EelasticSearch安装 Docker安装 docker run -d --name es7 -e ES_JAVA_POTS"-Xms256m -Xmx256m" -e "discovery.typesingle-node" -v /home/206/es7/data/:/usr/share/elasticsearch/data -p 9200:9200 -p 9300:9300 elasticsearch:7.14.0 …...
问题与分类
设计问题 是否已经有类似的解决方案,是否需要当前的设计设计思路的文档话,背景-》 设计思路-》 好处与不足 -》 其他设计思路的对比(淘汰其他设计思路的原因) 设计思路的评审,如何评审,如何量化ÿ…...

021-Qt 配置GitHub Copilot
Qt 配置GitHub Copilot 文章目录 Qt 配置GitHub Copilot项目介绍 GitHub Copilot配置 GitHub CopilotQt 前置条件升级QtGitHub Copilot 前置条件激活的了GitHub Copilot账号安装 Neovim 启用插件,重启Qt配置 GitHub Copilo安装Nodejs下载[copilot.vim](https://gith…...

如何使用 PostgreSQL 进行数据迁移和整合?
PostgreSQL 是一个强大的开源关系型数据库管理系统,它提供了丰富的功能和灵活性,使其成为许多企业和开发者的首选数据库之一。在开发过程中,经常会遇到需要将数据从一个数据库迁移到另一个数据库,或者整合多个数据源的情况。…...

Qt Signals Slots VS QEvents - Qt跨线程异步操作性能测试与选取建议
相关代码参考:https://gitcode.net/coloreaglestdio/qtcpp_demo/-/tree/master/qt_event_signal 1.问题的由来 在对 taskBus 进行低延迟改造时,避免滥用信号与槽起到了较好的作用。笔者在前一篇文章中,叙述了通过避免广播式地播发信号&…...

Postgres 和 MySQL 应该怎么选?
PostgreSQL和MySQL是两个流行的关系型数据库管理系统(DBMS)。它们都具有一些相似的功能,但也有一些区别。 在选择使用哪个DBMS时,需要考虑多个因素,包括性能、可扩展性、安全性、功能丰富度、生态系统支持等。下面是对…...

【在英伟达nvidia的jetson-orin-nx和PC电脑ubuntu20.04上-装配ESP32开发调试环境-基础测试】
【在英伟达nvidia的jetson-orin-nx和PC电脑ubuntu20.04上-装配ESP32开发调试环境-基础测试】 1、概述2、实验环境3、 物品说明4、参考资料与自我总结5、实验过程1、创建目录2、克隆下载文件3、 拉取子目录安装和交叉编译工具链等其他工具4、添加环境变量6、将样例文件拷贝到桌面…...
我终于搞明白了HTTPS协议了!超长文章!
HTTPS协议是现代互联网中非常重要的一种安全协议,它能够在客户端和服务器之间建立一条安全的通信渠道,确保用户的隐私和数据安全。下面我来详细介绍HTTPS协议的相关知识。 HTTP协议的缺点 HTTP协议是互联网中的一种应用层协议,它负责客户端…...
Golang Testify介绍
简介 Golang是一种编译型语言,由Google开发,已经成为了Web开发领域中非常受欢迎的语言之一。在Golang生态系统中,有许多用于编写测试的框架和库,其中Testify是其中一个非常流行的测试框架。 Testify是一个用于编写测试的扩展包&…...

DALL·E 3怎么用?DALL·E 3如何申请开通 ?DALL·E 3如何免费使用?AI绘画教程来喽~
一、引言 DALLE 3 是 OpenAI 在上个月(2023 年 9 月)发布的一个文生图模型。 相对于 Midjourney 以及 Stable Diffusion,DALLE 3 最大的便利之处在于,用户不需要掌握 Prompt 的写法了,直接自然语言描述即可。 甚至还…...

安装 Dispatch 库
首先,我们需要安装 Dispatch 库。在命令行中运行以下命令来安装 Dispatch: $ sbt console然后,在 Scala 控制台中,导入所需的库: import dispatch._接下来,我们需要设置代理服务器。在 Dispatch 中&#…...

【Unity程序技巧】异步保险箱管理器
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:Uni…...

ChatGPT 助力英文论文翻译和润色
文章目录 一、前言二、主要内容1. 中英互译2. 中文润色3. 英文润色 三、总结 🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 随着全球化的推进,跨文化交流变得越来越重要。在学术领域,英文论文的质量对于研究成果的传…...
【2024秋招】腾讯云智武汉后端开发一面 2023-9-20
1 java 1.1 hashMap 1.2 哈希冲突的解决方法 1.3 讲解一下CAS的aba问题 1.4 concurrentHashMap的并发方案为什么要使用cas ConcurrentHashMap 是 Java 并发包 java.util.concurrent 中的一个重要组件,用于提供高并发、高性能、线程安全的哈希映射。为了达到这样…...
k8s-----16、配置管理-ConfigMap
ConfigMap 1、作用2、以volume形式进行挂载2.1 创建配置文件2.2 创建ConfigMap文件2.3 最终的yaml文件 3、以变量形式进行挂载3.1 创建configmap文件3.2 书写最终yaml文件 1、作用 存储不加密的数据到etcd中,以变量或者volume形式挂载到pod的容器中场景:…...
QML QTP0001 not set 警告
使用QML的时候发现有这个警告。查阅资料之后发现解决办法。 大概的意思是说现在:/qt/qml/ 这个前缀是QML模块资源文件的前缀,而之前是:/ 这是从QT6.5开始的,旧的前缀被标记为废弃的。文档还说在使用qt_add_qml_module()不指定RESOURCE_PREFIX是新版的前…...

Mac M1编译 swift 5.8.1源码
参考链接:https://github.com/apple/swift/blob/main/docs/HowToGuides/GettingStarted.md#system-requirements 编译 Swift 5.8 源码-六虎 解决M1芯片的Homebrew安装问题--For M1使用者_m1 homebrew安装_a_52hz的博客-CSDN博客 建议全程梯子 一、检查和配置环境…...

[极客大挑战 2019]EasySQL
【解题思路】 1.打开靶机链接 2.输入数据进行尝试 输入1,1: 可以在导航栏里面看到username和password的变量。 3.使用万能密码 username:1 or 11# username:任意数据 password:任意数据 …...

统信UOS技术开放日:四大领域全面接入AI大模型能力
1024是程序员的节日,10月24日,统信举办2023统信UOS技术开放日暨deepin Meetup北京站活动,发布与大模型同行的UOS AI、浏览器AI助手、邮箱AI助手、自然语言全局搜索、畅写在线等多项最新AI技术与产品应用。 统信软件高级副总经理、CTO、深度社…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...