C++ : STL容器(适配器)之stack、queue剖析

在这里插入图片描述

STL容器适配器之stack、queue剖析

  • 一、stack、queue的接口
    • (一)stack 接口说明
    • (二)queue 接口说明
  • 二、stack、queue的模拟实现
    • (一)stack、queue是容器适配器
      • stack、queue底层默认容器--deque
        • 1、deque概念及原理
        • 2、stl中deque迭代器的实现(部分)
    • (二)stack的模拟实现
    • (三)queue的模拟实现
  • 三、优先队列
    • (一)优先队列的概念
    • (二)优先队列的接口说明
    • (三)优先队列的模拟实现
  • 四、结束语

一、stack、queue的接口

(一)stack 接口说明

  • stack()
    • 构造空的栈
  • empty()
    • 检测stack是否为空
  • size()
    • 返回stack中元素的个数
  • top()
    • 返回栈顶元素的引用
  • push()
    • 将元素val压入stack中
  • pop()
    • 将stack中尾部的元素弹出

(二)queue 接口说明

  • empty:
    • 检测队列是否为空
  • size:
    • 返回队列中有效元素的个数
  • front:
    • 返回队头元素的引用
  • back:
    • 返回队尾元素的引用
  • push_back:
    • 在队列尾部入队列
  • pop_front:
    • 在队列头部出队列

二、stack、queue的模拟实现

(一)stack、queue是容器适配器

虽然stackqueue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stackqueue只是对其他容器的接口进行了包装,STL中stackqueue默认使用deque.

stack、queue底层默认容器–deque

1、deque概念及原理

deque(双端队列):可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个
动态的二维数组,其底层结构如下图所示:
在这里插入图片描述

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问
的假象,落在了deque的迭代器身上

2、stl中deque迭代器的实现(部分)

在这里插入图片描述
在stl源码实现中,下面截取了迭代器的部分,有很多知识值得学习。

1、普通迭代器和const迭代器实现技巧

我们知道const对象的实现就是不能修改值,因此只需要在实现迭代器时针对一下->*的返回值即可,源码库中使用两个模板参数巧妙的解决这个问题。

2、非类型模板参数

在模板进阶中我们会讲到非类型模板参数的使用,使用size_t作为参数相当于一个宏的使用。
template <class T, class Ref, class Ptr, size_t BufSiz>

3、重载的复用

先实现重载符号 += 接着的 +、-、-=都采用了复用的方式,使得代码更简洁。
在实现++、–时,先实现前置++,前置–,再实现后置++,后置–,这里也可以复用

#pragma once
template <class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {typedef __deque_iterator<T, T&, T*, BufSiz>             iterator;typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;typedef T value_type;typedef Ptr pointer;typedef Ref reference;typedef T** map_pointer;typedef ptrdiff_t difference_type;typedef __deque_iterator self;//构造函数//有参构造__deque_iterator(T* x, map_pointer y): cur(x), first(*y), last(*y + buffer_size()), node(y) {}//默认构造__deque_iterator() : cur(0), first(0), last(0), node(0) {}//拷贝构造__deque_iterator(const iterator& x): cur(x.cur), first(x.first), last(x.last), node(x.node) {}//更新结点信息void set_node(map_pointer new_node) {node = new_node;first = *new_node;last = first + difference_type(buffer_size());}//运算符重载reference operator*() const { return *cur; }pointer operator->() const { return &(operator*()); }self& operator++() {++cur;if (cur == last) {set_node(node + 1);cur = first;}return *this;}self operator++(int) {self tmp = *this;++*this;return tmp;}self& operator--() {if (cur == first) {set_node(node - 1);cur = last;}--cur;return *this;}self operator--(int) {self tmp = *this;--*this;return tmp;}self& operator+=(difference_type n) {difference_type offset = n + (cur - first);if (offset >= 0 && offset < difference_type(buffer_size()))cur += n;else {difference_type node_offset =offset > 0 ? offset / difference_type(buffer_size()): -difference_type((-offset - 1) / buffer_size()) - 1;set_node(node + node_offset);cur = first + (offset - node_offset * difference_type(buffer_size()));}return *this;}self operator+(difference_type n) const {self tmp = *this;return tmp += n;}self& operator-=(difference_type n) { return *this += -n; }self operator-(difference_type n) const {self tmp = *this;return tmp -= n;}reference operator[](difference_type n) const { return *(*this + n); }bool operator==(const self& x) const { return cur == x.cur; }bool operator!=(const self& x) const { return !(*this == x); }bool operator<(const self& x) const {return (node == x.node) ? (cur < x.cur) : (node < x.node);}//成员变量
private:T* cur;T* first;T* last;map_pointer node;
};

(二)stack的模拟实现

通过stack的实现可以看出,stack的实现是基于deque栈的实现就是将双端队列进行包装,这个过程就像是deque是交流电,而stack就是这个插头,为用户提供需要的接口。

#pragma once
#include<vector>
#include<list>
#include<deque>
using namespace std;namespace wgm {template<class T, class Container = deque<T>>class stack {public:void push(const T& val) {_con.push_back(val);}void pop() {_con.pop_back();}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}const T& top()  const{return _con.back();}private:Container _con;};
}

(三)queue的模拟实现

stack类似,在它的参数列表中也有一个参数类型Container(容器),它也存在默认参数deque。这里的参数不能传入vector,因为vector不支持头部出元素的pop_front操作。

#pragma once
#include<vector>
#include<list>
#include<deque>
using namespace std;namespace wgm {template<class T, class Container = deque<T>>class queue {public:void push(const T& val) {_con.push_back(val);}void pop() {_con.pop_front();}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}const T& front() const{return _con.front();}const T& back() const{return _con.back();}private:Container _con;};
}

三、优先队列

(一)优先队列的概念

优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大(小)的。实际上,这就和之前学过的数据结构堆的性质一样。

(二)优先队列的接口说明

  • empty():
    • 检测容器是否为空
  • size():
    • 返回容器中有效元素个数
  • front():
    • 返回容器中第一个元素的引用
  • push_back():
    • 在容器尾部插入元素
  • pop_back():
    • 删除容器尾部元素

(三)优先队列的模拟实现

#pragma once
#include<vector>
#include<iostream>
using namespace std;namespace wgm {template <class T>struct less{bool operator() (const T& x, const T& y) const{return x < y;}};template <class T>struct greater{bool operator() (const T& x, const T& y) const{return x > y;}};template<class T , class Container = vector<T>, class Compare = less<T>>class priority_queue {public:
#define FATHER(i) (((i) - 1) / 2)
#define LEFT(i) (((i) * 2) + 1)
#define RIGHT(i) (((i) * 2) + 2)void AdjustUp(int i){Compare cmp;while (FATHER(i) >= 0 && Compare()(_con[FATHER(i)], _con[i])) {swap(_con[i], _con[FATHER(i)]);i = FATHER(i);}}void AdjustDown(int i){while (LEFT(i) < _con.size()) {int l = LEFT(i), r = RIGHT(i), ind = i;Compare cmp;if (cmp(_con[ind], _con[LEFT(i)])) ind = LEFT(i);if (RIGHT(i) < _con.size() && cmp(_con[ind], _con[RIGHT(i)])) ind = RIGHT(i);if (ind == i) break;swap(_con[i], _con[ind]);i = ind;}}void push(const T& val){_con.push_back(val);AdjustUp(_con.size() - 1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}bool empty(){return _con.empty();}const T& top(){return _con[0];}size_t size(){return _con.size();}private:Container _con;};
}

四、结束语

这个部分相对于之前学的容器要简单,只不过这个双端队列的实现源码还是挺有意思的,可以尝时着实现实现。

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

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

相关文章

Kubernetes的基本构建块和最小可调度单元pod-0

文章目录 一&#xff0c;什么是pod1.1pod在k8s中使用方法&#xff08;1&#xff09;使用方法一&#xff08;2&#xff09;使用方法二 1.2pod中容器的进程1.3pod的网络隔离管理&#xff08;1&#xff09;pause容器的作用 1.4 Pod分类&#xff1a;&#xff08;1&#xff09;自主式…

【CUDA】认识CUDA

目录 一、CUDA编程 二、第一个CUDA程序 三、CUDA关键字 四、device管理 4.1 初始化 4.2 Runtime API查询GPU信息 4.3 决定最佳GPU CUDA C 编程指南CUDA C在线文档&#xff1a;CUDA C 编程指南 CUDA是并行计算的平台和类C编程模型&#xff0c;能很容易的实现并行算法。只…

知识中台如何在精简供应链管理中发挥作用?

您如何与供应商沟通并分享您的最佳实践&#xff1f;您如何确保供应商了解您的基准&#xff1f;如果您正在为这些问题烦恼&#xff0c;请不要担心&#xff0c;本文章将为您提供宝贵的见解。 构建具备弹性的供应链模型&#xff0c;其关键在于知识中台的数据质量。若缺乏数据支撑…

Python 在PDF中绘制形状(线条、矩形、椭圆形等)

在PDF中绘制图形可以增强文档的视觉效果。通过添加不同类型的形状&#xff0c;如实线、虚线、矩形、圆形等&#xff0c;可以使文档更加生动有趣&#xff0c;提高读者的阅读兴趣。这对于制作报告、演示文稿或是教材特别有用。本文将通过以下几个示例介绍如何使用Python 在PDF中绘…

Gitlab-执行器为Kubetnetes时的注意事项,解决DNS解析问题

一、Gitlab-Runner 这里对于Runner的理解非常重要。 具体执行ci流水线的叫执行器。执行器可以部署是shell、docker、k8s的pod.执行完任务则生命周期结束。 管理执行器的叫Gitlab-Runner。Runner则是与Gitlab Server的Ci agent.(可以简单这么理解) 二、执行器为Kubetnetes时,DN…

大数据新视界 -- 大数据大厂之 Impala 性能优化:新技术融合的无限可能(下)(12/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

讨论一个mysql事务问题

最近在阅读一篇关于隔离级别的文章&#xff0c;文章中提到了一种场景&#xff0c;我们下面来分析一下。 文章目录 1、实验环境2、两个实验的语句执行顺序3、关于start transaction和start transaction with consistent snapshot4、实验结果解释4.1、实验14.2、实验24.3、调整实…

json绘制热力图

首先需要一段热力信息的json&#xff0c;我放在头部了。 然后就是需要de-geo库了。 实现代码如下&#xff1a; import * as d3geo from d3-geoimport trafficJSON from ../assets/json/traffic.jsonlet geoFun;// 地理投影函数// let info {max: Number.MIN_SAFE_INTEGER,mi…

K8S之Prometheus 部署(二十)

部署方式&#xff1a;https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/prometheus 源码目录&#xff1a;kubernetes/cluster/addons/prometheus 服务发现&#xff1a;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kube…

kafka中节点如何服役和退役

服役新节点 1&#xff09;新节点准备 &#xff08;1&#xff09;关闭 bigdata03&#xff0c;进行一个快照&#xff0c;并右键执行克隆操作。 &#xff08;2&#xff09;开启 bigdata04&#xff0c;并修改 IP 地址。 vi /etc/sysconfig/network-scripts/ifcfg-ens33修改完记…

【Three.js基础学习】21.Realistic rendering

前言 课程回顾 渲染器 1.色调映射 值意在将高动态范围](HDR)值转换为低动态范围(LDR) Three.is中的色调映射实际上会伪造将LDR转换为HDR的过程&#xff0c;即使颜色不是HDR&#xff0c; 结果会产生非常逼真的渲染效果 THREE .NoToneMapping (default) 无色调映射 THREE.Linear…

ORB_SLAM3安装

ORB_SLAM3安装 一.前期准备1.1ubuntu查看当前版本的命令1.2 根据ubuntu版本&#xff0c;更新下载软件源1.3 先下载git1.4 vim语法高亮1.5 常见的linux命令 二.ORB-SLAM3下载2.1 ORB_SLAM3源码下载2.2 安装依赖库2.2.1 依赖库2.2.2 安装pangolin2.2.3 安装opencv2.2.4 Eigen3安装…

无需云端!国产开源大语言模型llama.cpp本地实战

作者&#xff1a;高瑞冬 注&#xff1a; 文章是2023年底写的。代码和运行方式虽有些旧&#xff0c;但基本原理一样。现在出来ollama&#xff0c;vllm等工具框架用来本地部署大模型&#xff0c;顺便更新一下。 [TOC](最后有彩蛋) 背景 上海人工智能实验室与商汤科技…

横向思维导图前端样式

追溯记录图路上 代码如下 index.vue <template><div style"margin-left: 5%;margin-top: 6%"> <el-form style"margin-top: -5%; " :inline"true"><el-form-item label"药品名称"><el-select v-model&qu…

清华大学提出Mini-Omni2:开源多模态模型,功能与GPT-4o媲美!

&#x1f310; 在人工智能领域&#xff0c;多模态模型的发展正如火如荼。今天&#xff0c;我们要介绍的是由清华大学提出的Mini-Omni2&#xff0c;这是一个开源的多模态语言模型&#xff0c;它在功能上与GPT-4o相媲美&#xff0c;能够理解和生成视觉、听觉和文本内容&#xff0…

HarmonyOS入门 : 获取网络数据,并渲染到界面上

1. 环境搭建 开发HarmonyOS需要安装DevEco Studio&#xff0c;下载地址 : https://developer.huawei.com/consumer/cn/deveco-studio/ 2. 如何入门 入门HarmonyOS我们可以从一个实际的小例子入手&#xff0c;比如获取网络数据&#xff0c;并将其渲染到界面上。 本文就是基于…

msvcr100.dll丢失怎么解决?高效靠谱的六种解决方法分享

在我们使用电脑的时候&#xff0c;有一种叫动态链接库&#xff08;DLL&#xff09;的文件特别重要。比如&#xff0c;msvcr100.dll是Microsoft Visual C 2010 Redistributable包里的一部分&#xff0c;很多应用程序在运行的时候都需要用到它。但是&#xff0c;有些用户在使用的…

【C++练习】二进制到十进制的转换器

题目&#xff1a;二进制到十进制的转换器 描述 编写一个程序&#xff0c;将用户输入的8位二进制数转换成对应的十进制数并输出。如果用户输入的二进制数不是8位&#xff0c;则程序应提示用户输入无效&#xff0c;并终止运行。 要求 程序应首先提示用户输入一个8位二进制数。…

【SpringBoot】19 文件/图片下载(MySQL + Thymeleaf)

Git仓库 https://gitee.com/Lin_DH/system 介绍 从 MySQL 中&#xff0c;下载保存的 blob 格式的文件。 代码实现 第一步&#xff1a;配置文件 application.yml spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8datasource:driver-class-name: com.mysql.…

C++——异常

异常是在程序执行的过程中发生了某种错误&#xff0c;异常的处理机制允许我们讲发生的异常抛出给程序的另外一部分&#xff0c;对这个错误进行处理。这个机制让问题检测的环节和问题处理的环节分离。检测环节只需要负责检测即可&#xff0c;无需关系解决的细节问题。在C语言中处…