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

【C++】stack和queue的模拟实现

目录

  • 一、stack和queue的模拟实现
    • 1.1 容器适配器
    • 1.2 stack的模拟实现
    • 1.3 queue的模拟实现
    • 1.4 deque的了解认识
    • 1.5 deque的优缺点
    • 1.6 为什么选择`deque`作为`stack和queue`的底层默认容器

在这里插入图片描述

个人主页<—请点击
C++专栏<—请点击

一、stack和queue的模拟实现

1.1 容器适配器

C++标准库(STL)中,容器适配器(Container Adaptors)是一种特殊的容器,它们基于现有的STL容器(如vector、deque、list等)进行封装,提供了一种受限的、特定用途的接口。容器适配器本身并不直接管理内存或存储元素,而是依赖底层容器来实现功能,并通过限制或扩展接口来满足特定的数据结构需求。

容器适配器的核心特点

  • 基于现有容器适配器(如stack、queue、priority_queue)通过组合一个底层容器(如deque、vector)来实现功能。
  • 接口受限:仅暴露特定操作(如stack只允许一端操作(后进先出),queue是先进先出)
  • 不提供迭代器:无法直接遍历适配器中的元素(例如不能对stack用for(auto it : s))
  • 复用底层容器的实现:内存管理、元素存储等均由底层容器处理。

1.2 stack的模拟实现

stack容器的基本使用方法是push(尾插)、pop(尾删)、size()、empty()、top()。所以它的底层容器都必须能够使用这些方法,其中vector就是符合的,但STL库中使用了deque,这个容器也能完全符合特点,我们稍后作为了解。
在这里插入图片描述
模拟实现代码:

namespace ST
{template<class T, class Container = deque<T>>class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}T& top(){return _con.back();}const T& top() const{return _con.back();}private:Container _con;};
}

由于stack所有的接口里面的功能实现都是使用底层容器的,所以直接调用底层容器的成员函数就好了。

测试

void test1()
{ST::stack<int> st;st.push(1);st.push(2);st.push(3);st.push(4);st.push(5);while (st.size()){cout << st.top() << " ";st.pop();}
}

在这里插入图片描述

1.3 queue的模拟实现

queue的基本使用方法是push(尾插)、pop(头删)、front()、back()、size()、empty()。其中它所需求的这些功能list是具备的,但STL库中依旧使用了deque
在这里插入图片描述

模拟实现

namespace QUE
{template<class T,class Container = deque<T>>class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}T& front(){return _con.front();}const T& front() const{return _con.front();}T& back(){return _con.back();}const T& back() const{return _con.back();}private:Container _con;};
}

测试:

void test2()
{QUE::queue<int> q;q.push(1);q.push(2);q.pop();cout << q.front() << " ";q.push(3);q.push(4);q.push(5);while (q.size()){cout << q.front() << " ";q.pop();}
}

在这里插入图片描述

1.4 deque的了解认识

deque(双端队列,全称double-ended queue)C++标准模板库(STL)中的一个重要容器,它结合了vectorlist的优点,提供了高效的双端插入和删除操作。
在这里插入图片描述
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:
在这里插入图片描述
双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,重担落在了deque迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:
在这里插入图片描述
在这里插入图片描述

指针成员作用示意图对应位置
cur指向当前迭代器访问的具体元素(当前块的某个位置)图中0/1/2等元素的直接指针
first指向当前所属内存块的起始地址(块的首元素)图中每块的第一个元素地址
last指向当前所属内存块的结束地址(块的尾后位置)图中每块的最后一个元素的下一位
node指向中央映射表(map)中当前块的控制节点(保存该块的指针)图中map数组的某个槽位

协作关系
1、定位元素

  • 通过node找到当前块在中央映射表中的指针,再结合first/last确定块的范围。
  • cur[first, last)范围内移动,访问具体元素。

2、跨块跳转

  • cur移动到last(如++iter到块末尾),迭代器会:
  • 通过node找到下一个块的指针
  • 更新first/last为新块的边界
  • cur指向新块的起始位置(first)

3、反向移动

  • cur移动到first之前时(如--iter到块开头),迭代器会:
  • 通过node找到上一个块的指针
  • 更新first/last
  • cur指向上一块的末尾(last - 1)

1.5 deque的优缺点

vector比较,deque的优势:头删时不需要搬移元素,在扩容时也不需要搬移大量元素,效率比vector高。
list比较,deque的优势:其底层是连续空间,空间利用率比较高,不需要存储额外字段。

deque的致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和listdeque的应用并不多,而目前能看到的一个应用就是,在STL用其作为stack和queue的底层容器。

1.6 为什么选择deque作为stack和queue的底层默认容器

stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作;在stack中元素增长时,dequevector的效率高(扩容时不需要搬移大量数据)queue中的元素增长时,deque不仅效率高,而且内存使用率高。可以说stack和queue完美利用了deque的优点,并且完美避开了它的缺陷。

总结:
以上就是本期博客分享的全部内容啦!如果觉得文章还不错的话可以三连支持一下,你的支持就是我前进最大的动力!
技术的探索永无止境! 道阻且长,行则将至!后续我会给大家带来更多优质博客内容,欢迎关注我的CSDN账号,我们一同成长!
(~ ̄▽ ̄)~

http://www.dtcms.com/a/299083.html

相关文章:

  • 【C++】定义常量
  • SpringBoot连接Sftp服务器实现文件上传/下载(亲测可用)
  • Java中List集合对象去重及按属性去重
  • 【Linux系统】理解硬件 | 引入文件系统
  • MySQL数据库本地迁移到云端完整教程
  • 部署上线你的项目
  • 【Git】实用Git操作指南:从入门到高效协作
  • 小米携手云轴科技ZStack获信通院可信云用户典型实践奖
  • 大语言模型 LLM 通过 Excel 知识库 增强日志分析,根因分析能力的技术方案(2):LangChain + LlamaIndex 实现
  • Nanopct6SDK问题汇总与解决方案
  • 【架构】Docker简单认知构建
  • 【工程化】浅谈前端构建工具
  • Python爬虫实战:研究purl库相关技术
  • Mistral AI开源 Magistral-Small-2507
  • 密码学系列 - 密钥派生
  • 界面规范3-列表下
  • “给予” 超越 “莲花”,支持图片在线编辑
  • AI是否会终结IT职业?深度剖析IT行业的“涌现”与重构
  • 【GaussDB】构建一个GaussDB的Docker镜像
  • 【GaussDB】如何从GaussDB发布包中提取出内核二进制文件
  • window下MySQL安装(二)疑难解答
  • Apache Doris Data Agent 解决方案:开启智能运维与数据治理新纪元
  • excel删除重复项场景
  • Java面试题及详细答案120道之(021-040)
  • 字节跳动扣子 Coze 宣布开源:采用 Apache 2.0 许可证,支持商用
  • Qt 远程过程调用(RPC)实现方案
  • 网络基础19--OSPF路由业务多区域
  • 【Android】相对布局应用-登录界面
  • Java 中 System 类零度解析
  • 4N90-ASEMI电机控制专用4N90