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

【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.xdnf.cn/news/16357.html

相关文章:

  • Java基础day17-LinkedHashMap类,TreeMap类和集合工具类
  • 基于POD和DMD方法的压气机叶片瞬态流场分析与神经网络预测
  • 基于遗传算法的多无人车协同侦察与安全保护策略优化
  • CUDA杂记--FP16与FP32用途
  • Redis面试精讲 Day 5:Redis内存管理与过期策略
  • 汇编语言中的通用寄存器及其在逆向工程中的应用
  • 计划任务(at和cron命令介绍及操作)
  • MySQL事务原理
  • 应用程序 I/O 接口
  • 【MySQL 数据库】MySQL基本查询(第二节)
  • 系统性学习C语言-第二十三讲-文件操作
  • 谷歌无法安装扩展程序解决方法(也许成功)
  • Kubernetes 与 Docker的爱恨情仇
  • STM32-定时器的基本定时/计数功能实现配置教程(寄存器版)
  • 【工具】好用的浏览器AI助手
  • 用unity开发教学辅助软件---幼儿绘本英语拼读
  • 【深度学习新浪潮】什么是GUI Agent?
  • java面试复习(spring相关系列)
  • 【机器学习-2】 | 决策树算法基础/信息熵
  • 【RocketMQ】一分钟了解RocketMQ
  • Earth靶机攻略
  • linux线程概念和控制
  • 字符串缓冲区和正则表达式
  • Mingw 与MSYS2 与Cygwin区别
  • Linux如何执行系统调用及高效执行系统调用:深入浅出的解析
  • 基于深度学习的胸部 X 光图像肺炎分类系统(七)
  • 凝思系统6.0.80安装chorme,亲测可用
  • 如何创建或查看具有 repo 权限的 GitHub 个人访问令牌(PAT)
  • mount: /mnt/sd: wrong fs type, bad option, bad superblock on /dev/mmcblk1
  • FitCoach AI:基于React+CloudBase的智能健身教练应用开发全解析