【C++】10.stack和queue
创始人
2025-05-28 05:28:36
0

1.stack和queue

stack:栈

queue:队列

两者都是容器适配器

通过容器的push_back等功能来实现

容器适配器 都不支持迭代器遍历 因为他们通常都包含一些特殊性质

如果支持迭代器随便遍历 那他们无法很好的保持他的性质

2.stack/queue的实现/使用

#include 
#include 
#include 
#include 
#include 
using namespace std;namespace szh
{template//容器的类型 这个Container我也不知道 传什么就用什么class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}size_t size(){return _con.size();}bool empty(){return _con.empty();}T& top(){return _con.back();}private:Container _con;};void test_stack(){//stack> st;//利用模板传vector//stack> st;//利用模板传list 两者都可以实现stack> st;st.push(1);st.push(2);st.push(3);st.push(4);while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;}
}
  • 模板中定义一个Container的参数 用来表示容器
  • 这样就可以利用模板传容器
  • 直接调用容器的函数
  • 所有的内置功能都是容器的相关函数

 queue同理

#include 
#include 
#include 
#include 
using namespace std;namespace szh
{template//容器的类型 这个Container我也不知道 传什么就用什么class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}size_t size(){return _con.size();}bool empty(){return _con.empty();}T& front(){return _con.front();}T& back(){return _con.back();}private:Container _con;};void test_queue(){//queue> q;//vector不行 库里面的vector不支持头删 时间复杂度太高//queue> q;queue> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;}
}

总结一下:stl中的stack和queue是通过容器适配转换出来的 不是原生实现的 为什么呢? ->

复用 自己写一个容器适配也是可以的 所以没有写死

库里面是用deque来适配的

3.deque

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾

两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬

移元素;与list比较,空间利用率比较高。

  • 看起来好像可以替代vector和list的容器 但是实际呢?

排序效率相比vector较慢 不完美

下面测试一下效率

void dvcompare()
{deque d;vector v;const int n = 100000;int* a1 = new int[n];int* a2 = new int[n];srand(time(0));for (size_t i = 0; i < n; ++i){int x = rand();d.push_back(x);v.push_back(x);}size_t begin1 = clock();sort(d.begin(), d.end());size_t end1 = clock();size_t begin2 = clock();sort(v.begin(), v.end());size_t end2 = clock();cout << end1 - begin1 << endl;cout << end2 - begin2 << endl;//差了四倍左右//deque慢//vector快//所以deque替代不了vector 效率低了
}

使用

void test_deque()
{deque d;d.push_back(-1);d.push_back(1);d.push_back(2);d.push_back(5);d.push_back(0);d.push_front(10);for (size_t i = 0; i < d.size(); ++i){cout << d[i] << " ";}cout << endl;
}

  • deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组。
  • 双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂
  • 上面谈到效率不如vector 为什么要用deque?那为什么栈和队列的适配又可以使用呢?
  • 头尾的插入删除效率还是可以的 stack和queue没有用到随机访问 所以可以用
  • deque就是双端开口 可进可出

实际上deque的结构 如下图

  • 设计4个指针 类似小数组的组合

  • 如何管理多个小数组buffer呢?

    通过中控映射的方式 中控管理的指针数组 每个指针指向一个小数组

  • 如何实现opeartor[]的随机访问呢?

    通过指针的移动来访问数据

    需要计算访问的第i个数据在哪个buffer

    当数据量大了以后 效率就变低了

4.priorty_queue

优先级队列 底层就是堆 默认是大堆 但是缺省符号给了小于 小堆需要改变符号 变成大于

那么默认是大堆 如果想建小堆 那么需要一个一个换符号 很麻烦

这时模板的优势就来了 再增加一个模板参数 控制大于号还是小于号

//默认升序 怎么排降序 通过仿函数比较大小
void test_sort()
{vector v;v.push_back(5);v.push_back(1);v.push_back(2);v.push_back(4);//升序less //greater gt;//sort(v.begin(), v.end(), gt);sort(v.begin(), v.end(), greater());for (auto e : v){cout << e << " ";}cout << endl;
}

void test_priority_queue()
{//priority_queue pq;//默认大的优先级高 //默认是大堆priority_queue,greater> pq;//如果想变成小的优先级高 如何操作? 仿函数 #include pq.push(3);pq.push(1);pq.push(9);pq.push(4);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;
}

#include 
#include 
using namespace std;namespace szh
{//默认是大堆template,class Compare = less>//标准库默认是大堆 但是缺省给了小于class priority_queue//默认vector 底层是堆 logN 二叉树{public://从小到大就是符号变一下 其他都一样 有没有很好的方式取控制符号?templatestruct less{//仿函数 函数对象bool operator()(const T& x1, const T& x2){return x1 < x2;}};templatestruct greater{//仿函数 函数对象bool operator()(const T& x1, const T& x2){return x1 > x2;}};//向上调整void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0)//child==0的时候就不用调了{//if (_con[child] > _con[parent])if (com(_con[parent], _con[child]))//换顺序 默认是小于{swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}//向下调整void AdjustDown(int root){Compare com;int parent = root;int child = parent * 2 + 1;while (child < _con.size()){//选出左右孩子中大的那一个//if (child + 1 < _con.size() && _con[child + 1] > _con[child])if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))//换顺序 默认是小于号{++child;}//if (_con[child] > _con[parent])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);AdjustUp(_con.size() - 1);//向上调整 二叉树处}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);//向下调整}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 pq;//大堆priority_queue,greater> pq;//大于反而是小堆pq.push(3);pq.push(1);pq.push(9);pq.push(4);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;}
}

5.总结

  • 容器:string/vector/list/deque(序列式容器)

  • 适配器:stack/queue/priority_queue

  • 迭代器:iterator/const_iterator/reverse_iterator/const_reverse_iterator

  • 算法:sort/find/reverse

  • 仿函数:less/greater

  • deque的缺点:

    大量的频繁opeartor[]的效率低

    迭代器的遍历相对复杂 效率也有一些影响

  • vector缺点:

    头插头删的效率低 空间不够用了增容代价大

  • list缺点:

    不支持随机访问

  • priority_queue 优先级队列 大的小的谁优先级高是看场景的

    #include 包了队列和优先级队列

  • 面试问题:能否设计出一个数据结构 解决vector和list的缺点

    deque中控映射指针数组不够了增容就可以

    但对比vector 一起去堆相同的10w个数据排序 deque效率相比vector差了4-5倍

【C++】10.stack和queue 完

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...