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

C++入门之stl六大组件--stack和queue源码深度剖析及模拟实现

目录

前言

一、stack的介绍和使用

1.stack的介绍

2.stack的使用

3.stack的模拟实现

二、queue的介绍和使用

1.queue的介绍

2.queue的使用

3.queue的模拟实现

三、priority_queue的介绍和使用

1.priority_queue的介绍

2.priority_queue的使用

3.priority_queue的模拟实现

3.1解决一个topK问题

四、容器适配器

1.什么是容器适配器

2.stl中stack和queue的底层结构

3.deque的简单介绍(vector +list)

总结


前言

本文中的源码均在本地vs2019下测试无误,上传文件至gitee,地址为:https://gitee.com/a_young/stack_queue_-priority_queue


一、stack的介绍和使用

1.stack的介绍

通过阅读官方文档:

1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器并提供一组特定 的成员函数来访问其元素,将特定类作为其底层的元素特定容器的尾部(即栈顶)被压入和弹出。
3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下 操作:
  • empty:判空操作
  • back:获取尾部元素操作
  • push_back:尾部插入元素操作
  • pop_back:尾部删除元素操作
4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器, 默认情况下使用deque

2.stack的使用

  • stack() 构造空的栈
  • bool empty() const { return c.empty(); }检查stack是否为空
  •  size_type size() const { return c.size(); } 返回stack中元素个数
  •  reference top() { return c.back(); } 返回栈顶元素
  •  const_reference top() const { return c.back(); } 返回栈顶元素
  •  void push(const value_type& x) { c.push_back(x); } 将元素val压栈
  •  void pop() { c.pop_back(); }  将stack尾部元素弹出

3.stack的模拟实现

源码中使用的deque来作为栈的适配器,所以我们使用deque来模拟stack

template<class T, class Contanier = 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();}size_t size(){return _con.size;}bool empty(){return _con.empty();}private:Contanier _con;};void test_stack(){//stack<int, vector<int>>st;  //数组栈// stack<int,list<int>> st; 链式栈stack<int, deque<int>>st;st.push(1);st.push(2);st.push(3);st.push(4);while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;}
}

二、queue的介绍和使用

1.queue的介绍

1. 队列是一种容器适配器,专门用于在 FIFO 上下文 ( 先进先出) 中操作,其中从容器一端插入元素,另一端 提取元素。
2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类, queue 提供一组特定的 成员函数来访问其元素。元素从队尾入队列,从队头出队列。
3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作 :
empty :检测队列是否为空
size :返回队列中有效元素的个数
front :返回队头元素的引用
back :返回队尾元素的引用
push_back :在队列尾部入队列
pop_front :在队列头部出队列
4. 标准容器类dequelist 满足了这些要求。默认情况下,如果没有为 queue 实例化指定容器类,则使用标准容器 deque

2.queue的使用

queue() 构造空的队列
empty() 检测队列是否为空,是返回 true ,否则返回 false
size()     返回队列中有效元素的个数
front()    返回队头元素的引用
back()    返回队尾元素的引用
push()   在队尾将元素 val 入队列
pop()      将队头元素出队列

3.queue的模拟实现

#pragma once
#pragma once
#include<iostream>
#include<vector>
#include<stack>
#include<list>using namespace std;namespace jellytest
{//适配器模式/配接器 //队列 先进先出template<class T, class Contanier = 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();}private:Contanier _con;};void test_queue(){//stack<int, vector<int>>st;  //数组栈// stack<int,list<int>> st; 链式栈queue<int, deque<int>> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;}
}

三、priority_queue的介绍和使用

1.priority_queue的介绍

1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素 ( 优先队列中位于顶部的元 )
3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类, queue 提供一组特 定的成员函数来访问其元素。元素从特定容器的 尾部 弹出,其称为优先队列的顶部。
4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭 代器访问,并支持以下操作:
  • empty():检测容器是否为空
  • size():返回容器中有效元素个数
  • front():返回容器中第一个元素的引用
  • push_back():在容器尾部插入元素
  • pop_back() :删除容器尾部元素
5. 标准容器类 vector deque 满足这些需求。默认情况下,如果没有为特定的 priority_queue 类实例化指 定容器类,则使用 vector
6. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数 make_heap push_heap pop_heap 来自动完成此操作。

2.priority_queue的使用

优先级队列默认使用 vector 作为其底层存储数据的容器,在 vector 上又使用了堆算法将 vector 中元素构造成堆的结构,因此 priority_queue 就是堆,所有需要用到堆的位置,都可以考虑使用 priority_queue 。注意: 默认情况下 priority_queue 是大堆
priority_queue()/priority_queue(fifirst,last)   构造一个空的优先级队列
empty( ) 检测优先级队列是否为空,是返回true,否则返回 false
top( )  返回优先级队列中最大(最小元素),即堆顶元素
push(x)  在优先级队列中插入元素x
pop()  删除优先级队列中最大(最小)元素,即堆顶元素

3.priority_queue的模拟实现

通过上面的介绍,priority_queue的底层结构就是堆,因此此处只需对堆进行封装即可。stl中默认实现的是大堆。

这里先介绍一个新的概念--仿函数,使用仿函数定义的对象可以像函数一样使用,本质是调用运算符重载,如下定义:

struct less
{bool operator()(int x, int y){return x<y;}
}struct greater
{bool operator()(int x,int y){return x>y;}
}int main()
{Less lessfun; //声明一个对象cout<<lessfun(1,2)<<endl; // 1
}

stl中使用模板类,可以比较不止内置类型

3.1解决一个topK问题

topK问题实际上是找出文件中所有数的最大的前K个.

方法1:可以构造一个大堆,pop出前K个。

分析方法1:假设N很大,K很小,N个数都需要存到内存中,很浪费资源。

方法2:构造一个K个数的小堆,后面的数依次和堆顶元素进行比较,大于堆顶元素就进堆,替换堆顶元素,然后向下调整。最后前K大的数所有的就在堆中。

分析方法2:时间复杂度O(N*logK),空间复杂度O(K)

综上对两种方法比较,选择方法2来实现

template<class T>
struct less
{bool operator()(T & x, T& y){//如果是自定义类型这里需要自己实现运算符重载return x<y;}
}//创建一个小堆
template<class T,class Container = deque<T> ,class Compare = greter<T>>
class priority_queue
{public://向下调整void adjust_down(int parent){Compare com;int child = 2*parent +1;while(chile < _con.size()){//  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]);child = parent;parent = 2*child+1;}else{break;}}}//向上调整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 push(){_con.push_back(x);adjust_up(_con.size()-1);}void pop(){swap(_con[0],_con[_con.size()-1]);_con.pop_back();adjust_down(0);}const T& top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;
}void test_priority_queue()
{priority_queue<int,deque<int>,less<int>> pq;pq.push(0);pq.push(1);pq.push(2);pq.push(3);while(!pq.empty()){cout<<pq.top()<<" ";pq.pop();}

四、容器适配器

1.什么是容器适配器

2.stl中stack和queue的底层结构

3.deque的简单介绍(vector +list)

deque(双端队列):是一种双开口的“连续”空间的数据结构,双开口的含义是:可以在头尾两端进行插入删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不用挪动元素,与list比较,空间利用率较高。缺点就是:中间插入删除麻烦

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组。头插的时候,就在中控数组前面插入一个指针,尾插在中控尾巴插入一个

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护“整体连续”以及随机访问的假象,落在deque的迭代器上,因此deque的迭代器设计就比较复杂。

为什么选择 deque 作为 stack queue 的底层默认容器
stack 是一种后进先出的特殊线性数据结构,因此只要具有 push_back() pop_back() 操作的线性结构,都可以作为 stack 的底层容器,比如 vector list 都可以; queue 是先进先出的特殊线性数据结构,只要具有 push_back pop_front 操作的线性结构,都可以作为 queue 的底层容器,比如 list 。但是 STL 中对 stack queue 默认选择 deque 作为其底层容器,
主要是因为:
1. stack queue 不需要遍历 ( 因此 stack queue 没有迭代器 ) ,只需要在固定的一端或者两端进行操作。
2. stack 中元素增长时, deque vector 的效率高 ( 扩容时不需要搬移大量数据 ) queue 中的元素增长 时, deque 不仅效率高,而且内存使用率高。
结合了 deque 的优点,而完美的避开了其缺陷。

总结

本文主要模拟实现了stack,queue,priority_queue的一些接口,简单介绍了什么是容器适配器。

相关文章:

C++入门之stl六大组件--stack和queue源码深度剖析及模拟实现

目录 前言 一、stack的介绍和使用 1.stack的介绍 2.stack的使用 3.stack的模拟实现 二、queue的介绍和使用 1.queue的介绍 2.queue的使用 3.queue的模拟实现 三、priority_queue的介绍和使用 1.priority_queue的介绍 2.priority_queue的使用 3.priority_queue的模…...

MyCat配置文件schema.xml讲解

1.MyCat配置 1.1 schema标签 如果checkSQLschema配置的为false&#xff0c;那么执行DB01.TB_ORDER时就会报错&#xff0c;必须用use切换逻辑库以后才能进行查询。 sqlMaxLimit如果未指定limit进行查询&#xff0c;列表查询模式默认为100,最多只查询100条。因为用mycat后默认数…...

Grafana集成prometheus(2.Grafana安装)

查找镜像 docker search grafana下载指定版本 docker pull grafana/grafana:10.0.1启动容器脚本 docker run -d -p 3000:3000 --namegrafana grafana/grafana:10.0.1查看是否启动 docker ps防火墙开启 检查防火墙3000端口是否开启 默认用户及密码 admin/admin 登录 ht…...

代码随想录算法训练营第五十七天| 647. 回文子串 516.最长回文子序列

代码随想录算法训练营第五十七天| 647. 回文子串 516.最长回文子序列 一、力扣647. 回文子串 题目链接 思路&#xff1a;对于字符串cabac&#xff0c;其中a,b,c,aba,cabac&#xff0c;都是回文子串&#xff0c;如果当前的字串是回文字串&#xff0c;那么它的字串中也会有回文…...

django 优化方式

前言 对于网站和Web APP来说&#xff0c;相同的类型的产品&#xff0c;响应速度越好&#xff0c;那么用户量就越高。不可否认的是&#xff0c;响应速度是用户黏粘性最好的方式之一&#xff0c;但往往不知道如何下手解决&#xff0c;希望这篇文章可以给予你一些思路 对于网站和…...

IDEA中怎么使用git下载项目到本地,通过URL克隆项目(giteegithub)

点击 新建>来自版本控制的项目 点击后会弹出这样一个窗口 通过URL拉取项目代码 打开你要下载的项目仓库 克隆>复制 gitee github也是一样的 返回IDEA 将刚刚复制的URL粘贴进去选择合适的位置点击克隆 下载完成...

09. Docker Compose

目录 1、前言 2、安装Docker Compose 2.1、Docker Compose版本 2.2、下载安装 3、初试Docker Compose 3.1、传统方案部署应用 3.2、使用编排部署应用 3.3、其他命令 3.3.1、ps 3.3.2、images 3.3.3、depends_on 3.3.4、scale 4、小结 1、前言 随着应用架构的不段…...

如何在shell脚本将node_modules里的文件复制一份到public文件里

项目背景&#xff1a;由于公司网络不连接公网&#xff0c;所以在绘制地图大屏项目时&#xff0c;需要我们将边界线数据包也部署起来&#xff0c;来获取边界线数据 解决方案&#xff1a; 1.让后端写个接口或者找个地方将数据包放到服务器即可 2.将数据包放到vue项目的public文…...

监控Redis的关键指标

Redis 也是一个对外服务&#xff0c;所以 Google 的四个黄金指标同样适用于 Redis。 1、延迟 在软件工程架构中&#xff0c;之所以选择 Redis 作为技术堆栈的一员&#xff0c;大概率是想要得到更快的响应速度和更高的吞吐量&#xff0c;所以延迟数据对使用 Redis 的应用程序至…...

Openlayers和leaflet如何选用?

在地图处理这块,Openlayers和Leaflet是非常有名的两个开源的JS框架,他们各有各的优势和劣势,对于刚刚步入此行业的开发者而言怎么选择框架呢? 作者做过一定的探索,在这里将成果分享给大家。 Openlayers 简介 Openlayers是一个基于Javacript开发,免费、开源的前端地图开…...

跟我学C++中级篇——三五法则

一、三五法则 三五法则&#xff0c;这个叫着有点上头&#xff0c;说实话&#xff0c;这个三五法则&#xff0c;未来会不会变成三六或者四七法则&#xff0c;没人知道&#xff0c;反正现在是三五法则。在《cPrimer》第四版中&#xff0c;叫三法则&#xff0c;在第五版第13.1.4章…...

aardio:用 WebView 模仿 mdict 界面

aardio&#xff1a;用 WebView 模仿 mdict 界面 import win.ui; /*DSG{{*/ mainForm win.form(text"aardio2";right889;bottom467) mainForm.add( button{cls"button";text"go";left335;top22;right399;bottom41;z2}; button2{cls"button…...

linq中的操作符

LINQ&#xff08;Language Integrated Query&#xff09;是一种用于.NET平台的查询语言&#xff0c;用于查询和操作各种数据源&#xff0c;如集合、数据库和XML。LINQ提供了一组标准查询操作符&#xff0c;用于执行各种查询操作。 LINQ&#xff08;Language Integrated Query&…...

数据结构【哈夫曼树】

哈夫曼树 哈夫曼树的概念哈夫曼树的构造构造算法的实现哈夫曼树应用哈夫曼编码哈夫曼编码的算法实现 哈夫曼树的概念 最优二叉树也称哈夫曼 (Huffman) 树&#xff0c;是指对于一组带有确定权值的叶子结点&#xff0c;构造的具有最小带权路径长度的二叉树。权值是指一个与特定结…...

SpringMVC基于SpringBoot的最基础框架搭建——包含数据库连接

SpringMVC基于SpringBoot的最基础框架搭建——包含数据库连接 背景目标依赖配置文件如下项目结构如下相关配置如下启动代码如下Controller如下启动成功接口调用成功 背景 工作做了一段时间&#xff0c;回忆起之前有个公司有线下笔试&#xff0c;要求考生做一个什么功能&#x…...

deepspeed zero3

zero3。它是纵向切分权重&#xff08;intra-layer&#xff0c;每一层的权重切成n块&#xff09;。但是这样会增加通讯时间。你可以根据自己的模型&#xff0c;估算下切分后的通讯量和通讯时间。其次&#xff0c;pipeline并行一般指横向切分权重&#xff08;inter-layer&#xf…...

代驾小程序怎么做

代驾小程序是一款专门为用户提供代驾服务的手机应用程序。它具有以下功能&#xff1a; 1. 预约代驾&#xff1a;代驾小程序允许用户在需要代驾服务时提前进行预约。用户可以选择出发地点、目的地以及预计用车时间&#xff0c;系统会自动匹配最合适的代驾司机&#xff0c;并确保…...

探索 AJAX 技术:实现动态数据交互的前端利器

简介&#xff1a; AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;技术在 Web 前端开发中扮演着重要的角色&#xff0c;它通过异步通信和动态内容更新&#xff0c;为用户带来更好的交互体验。本篇笔记将详细探索 AJAX 技术&#xff0c;并通过生动的代码演示来展示…...

深度学习Redis(3):主从复制

前言 在前面的两篇文章中&#xff0c;分别介绍Redis内存模型和Redis持久化 在Redis的持久化中曾提到&#xff0c;Redis高可用的方案包括持久化、主从复制&#xff08;及读写分离&#xff09;、哨兵和集群。其中持久化侧重解决的是Redis数据的单机备份问题&#xff08;从内存到…...

php笔记1

php环境 PHP作为一种服务器端脚本语言&#xff0c;可以在各种操作系统上运行。搭建PHP网站的环境&#xff0c;你需要以下几个要素&#xff1a; Web服务器&#xff1a;常见的选择有Apache、Nginx和IIS。你需要安装和配置其中一个服务器软件。PHP解释器&#xff1a;PHP是一种解…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...