C++(stack和queue)

1. stack的介绍、使用和实现

1.1 stack的介绍

stl里的stack其实和数据结构内的stack和前面数据结构的栈不能说百分百一样,但也有百分之90是一样的,他们的特性都是LIFO(last in first out)先进后出的原则,前面有类似的这里就不过多讲述;

这个是C++ stack的文档:stack - C++ Reference (cplusplus.com)


1.2 stack的使用

stack的主要的使用接口就那么几个,我们这里就直接上个主要的接口图和使用的代码;如下图和代码所示:

#include<iostream>
#include<stack>
using namespace std;void TestStack()
{//同前面list一样,他们都是个模板stack<int> st;//empty的使用if (!st.empty()){cout << " stack is not empty" << endl;}else{cout << "stack is empty" << endl;}//push的使用st.push(1);st.push(2);st.push(3);st.push(4);st.push(5);//empty的使用if (!st.empty()){cout << " stack is not empty" << endl;}else{cout << "stack is empty" << endl;}//size的使用cout << "The size of stack is:> " << st.size() << endl;//top的使用cout << "The top element of stack is:> " << st.top() << endl;//因为栈和队列没有迭代器,如果有迭代器的话那就可以访问任意位置的数据了,//不符合后进先出的原则//所以如果我们想打印栈内的数据需要这样走;cout << "The element of stack are:> ";while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;st.push(1);st.push(2);st.push(3);st.push(4);st.push(5);//pop的使用st.pop();st.pop();cout << "After pop the element of stack are:> ";while (!st.empty()){cout << st.top() << " ";st.pop();}
}int main()
{TestStack();return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:


1.3 stack的实现

由于在stl库内 stack不是一个简单的容器,而是一个容器适配器Container adaptor,举个例子,容器适配器就类似家里的插头,我们不仅可以用手机充电头去插头那给手机充电,还可以用电脑电源的充电头去给电脑充电,而手机充电头就类似list<int>,电脑充电头就类似vector<int>;如下代码可见;

#include<iostream>
#include<deque>
#include<stack>
#include<vector>
#include<list>
using namespace std;
//#include"stack.h"void teststack()
{//适配list容器stack<int, list<int>> st1;st1.push(1);st1.push(2);st1.push(3);st1.push(4);st1.push(5);cout << "The top is:> " << st1.top() << endl;st1.pop();st1.pop();cout << "The top is:> " << st1.top() << endl;while (!st1.empty()){cout << st1.top() << " ";st1.pop();}cout << endl;//适配vector容器stack<int, vector<int>> st2;st2.push(1);st2.push(2);st2.push(3);st2.push(4);st2.push(5);cout << "The top is:> " << st2.top() << endl;st2.pop();st2.pop();cout << "The top is:> " << st2.top() << endl;while (!st2.empty()){cout << st2.top() << " ";st2.pop();}
}
int main()
{teststack();return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:

那么我们实现stack的时候我们的类模板就不止一个传入的类型,还有一个类类型的变量接收;那具体的实现步骤就直接看代码,因为这个实现的底层其实也就是数组,但也可以用链表去实现前面数据结构的栈的篇章说过;如下代码所示:

#pragma once
#include"priority_queue.h"
#include<deque>
namespace lwt
{//stack在stl库内是被称作container adaptor(容器适配器)template<class T, class Container = deque<T>>class stack{public://尾插void push(const T& x){_con.push_back(x);}//尾删void pop(){_con.pop_back();}//取栈顶元素const T& top()const{return _con.back();}size_t size()const{return _con.size();}bool empty()const{return _con.empty();}private:Container _con;};
}

这里的成员变量用Container就是为了达到容器适配器的效果,如果传入的是vector<int>,那么就会执行vector<int> _con; 然后再进行插入删除,list也一样;那上面有一点就是deque是什么玩意,先保留这个疑问,下面一会会讲到;


2. queue的介绍、使用和实现

2.1 queue的介绍

stl里的queue和数据结构里的queue队列也类似,也是先进先出FIFO的特性,所以也不过多讲述;

这个是C++的queue的文档:queue - C++ Reference (cplusplus.com)


2.2 queue的使用

如下图和代码所示:

#include<iostream>
#include<deque>
#include<queue>
#include<stack>
#include<vector>
#include<list>
using namespace std;int main()
{queue<int, list<int>> que1;que1.push(1);que1.push(2);que1.push(3);que1.push(3);que1.push(4);que1.push(5);while (!que1.empty()){cout << que1.front() << " ";que1.pop();}cout << endl;//size的使用que1.push(1);que1.push(2);que1.push(3);que1.push(3);que1.push(4);que1.push(5);cout << "The size of que1 is:> " << que1.size() << endl;que1.front() = 9;cout << "The front of que1 is:> " << que1.front() << endl;return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:


2.3 queue的实现

stl库内的queue和上面的stack一样,都是容器适配器;增删查改实现的话其实就和前面的数据结构的队列实现的思路一样,所以不在这里过多讲述,直接上图和代码;

#pragma once
namespace lwt
{#include<deque>template<class T, class Container = 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();}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}

3. deque的介绍

在上面我们看到stack和queue的模板的类类型的缺省参数是deque,但上面没有讲,因为我想在下面另外讲解;deque,可能我们看到有个que就认为他就是队列,所以底层可能是用链表实现的,其实并不然,deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高,也可以说deque是list和vector的杂交版;

但实质上,其实deque并不是真正的连续的空间,而是由一段段连续的小空间拼排而成的,实际上deque就类似一个动态的二维数组;其结构如下图所示:

红色区域是一个中控数组,每次的插入和删除都是在中控数组的中间开空间,这个效率就很高了,为什么高呢?相比于链表,他的尾插和头插的效率更高,因为他每次都是开绿色块那样的空间大小,而链表每次头尾插需要进行开辟新的空间,开辟新的空间会造成效率降低;对于vector来说,头插就很方便了,他只需要在前面再new多一块空间,然后从后往前插入完成头插,而不需要挪动数据,

下图是他的具体结构

3.1 deque的缺陷

当deque遍历的时候要频繁的检测first是否等于last,如果等于就需要node+1,导致效率低下,所以一般要使用线性结构的时候大多数优先考虑list和vector,deque的应用场景不多,目前看见的应用是在STL里用其作为stack和queue的底层结构;

3.2 为什么选择deque作为stack和queue的底层结构

1.  stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进
行操作。
2.  在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的
元素增长时,deque不仅效率高,而且内存使用率高。

4. priority_queue的介绍和实现

4.1 priority_queue的介绍

        priority_queue又称优先级队列,它的第一个元素总是它所包含的元素中最大的,那这是不是就有点像我们前面数据结构学过的堆;其实优先级队列的底层就是堆,首先我们先来回忆一下堆的性质,堆分为大堆和小堆,大堆的每个树的父节点是树中最大的,小堆则反之,但是STL的priority_queue和我们数据结构那实现的堆的不同是,他是一个容器适配器,即只要符合他的特性的容器都可以拿来当他的底层,如下图就是优先级队列的特性;

而标准类vector和deque满足这些条件;还需要支持随机访问迭代器,因为完成建堆等操作,而 堆的底层就是顺序表,那就需要支持随机访问迭代器;


4.2 仿函数基础

在实现优先级队列之前我们还需要提一个点就是仿函数,仿函数顾名思义就是类似函数的东西,他实质上是一个类,他是重载了“()”的一个类,作用是用来做比较,例如如果我们想实现一个大堆的话,我们就需要修改建堆的大于小于号,那是不是太麻烦了,所以我们就延伸出了仿函数这个东西;举个例子,比如说我想让条件为arr[parent]>arr[child]的时候我们就可以定义一个类作为仿函数greater(arr[parent], arr[child] ),而我我想让条件改为arr[parent]<arr[child]的话就定义一个类作为仿函数less(arr[parent], arr[child];如下代码可见,这是使用,就需要在创建priority_queue的时候在最后面加一个greater<int>;

#include <vector>
#include <queue>
#include<iostream>
#include <functional> // greater算法的头文件
using namespace std;void TestPriorityQueue()
{// 默认情况下,创建的是大堆,其底层按照小于号比较vector<int> v{ 3,2,7,6,0,4,1,9,8,5 };priority_queue<int> q1;for (auto& e : v)q1.push(e);cout << q1.top() << endl;// 如果要创建小堆,将第三个模板参数换成greater比较方式priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());cout << q2.top() << endl;
}int main()
{TestPriorityQueue();return 0;
}

4.2 priority_queue的实现

优先级队列的实现也很简单,其实就是建堆,只不过在这里面添加多了一个仿函数进行判断是建小堆还是大堆,如下代码所示:

#pragma once
#include<vector>
template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};namespace lwt
{template<class T, class Container = vector<T> , class Compare = Less<T>>class priority_queue{public:void AdjustUp(int child){Compare  com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;	}}}void push(const T& x){_con.push_back(x);AdjustUp(_con.size()-1);}void AdjustDown(int parent){size_t child = parent * 2 + 1;Compare com;while (child < _con.size()){//看左右孩子谁大谁小,大堆那我们就要找到小的if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){++child;}if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){//pop就是堆删swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}const T& top(){return _con[0];}size_t size() const{return _con.size();}bool empty()const{return _con.empty();}private:Container _con;};}

END!

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

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

相关文章

VideoCLIP-XL:推进视频CLIP模型对长描述的理解

摘要 对比语言-图像预训练&#xff08;CLIP&#xff09;已被广泛研究并应用于众多领域。然而&#xff0c;预训练过程中对简短摘要文本的重视阻碍了CLIP理解长描述的能力。在视频方面&#xff0c;这个问题尤为严重&#xff0c;因为视频通常包含大量详细内容。在本文中&#xff…

如何看一个flutter项目的具体flutter版本

查看pubspec.lock文件 这个项目实际运行的就是 flutter 3.16.6 版本的

Leetcode 1489. 找到最小生成树里的关键边和伪关键边

1.题目基本信息 1.1.题目描述 给你一个 n 个点的带权无向连通图&#xff0c;节点编号为 0 到 n-1 &#xff0c;同时还有一个数组 edges &#xff0c;其中 edges[i] [fromi, toi, weighti] 表示在 fromi 和 toi 节点之间有一条带权无向边。最小生成树 (MST) 是给定图中边的一…

MFC扩展库BCGControlBar Pro v35.1新版亮点:改进网格控件性能

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.1已全新发布了&#xff0c;这个版本改进网格控件的性能、增强工具栏编辑器功能等。 …

【puppeteer】wvp-puppeteer制作 过程

目录 最后的结论 制作windows&ubuntu的docker 重启桌面上的docker 命令重启 通过 Docker Desktop 图形界面重启 制作centos docker 测试 参考文档 最后的结论 ubuntu && windows 使用 dualvenregistry:5000/wvp-puppeteer:1.0 centos7 使用&#xff1a;…

通过OpenCV实现 Lucas-Kanade 算法

目录 简介 Lucas-Kanade 光流算法 实现步骤 1. 导入所需库 2. 视频捕捉与初始化 3. 设置特征点参数 4. 创建掩模 5. 光流估计循环 6. 释放资源 结论 简介 在计算机视觉领域&#xff0c;光流估计是一种追踪物体运动的技术。它通过比较连续帧之间的像素强度变化来估计图…

第6篇:无线与移动网络

目录 引言 6.1 无线网络的基础概念 6.2 无线局域网&#xff08;WLAN&#xff09;与IEEE 802.11 6.3 蓝牙与无线个域网&#xff08;WPAN&#xff09; 6.4 无线城域网&#xff08;WMAN&#xff09;与WiMax 6.5 ZigBee与智能家居 6.6 移动蜂窝网络&#xff08;3G/4G/5G&…

【Linux】总线-设备-驱动模型

背景 前面&#xff0c;我们介绍了写驱动代码的一些常规步骤&#xff0c;并且也写了最基本的驱动代码&#xff0c;但是那些代码存在着问题&#xff0c;我们将硬件的信息都写进了驱动里了&#xff0c;如果我们在杂项设备驱动中控制led&#xff0c;那么会在硬件操作接口中包含硬件…

【SQL实验】数据库、表、模式的SQL语句操作

完整代码在文章末尾 1、数据库的建立、删除和修改操作 &#xff08;1&#xff09;使用SQL语句创建数据库EDUC&#xff0c;并进行如下设置&#xff1a; 数据库文件和日志文件的逻辑名称分别为&#xff1a;Student_data和Student_log&#xff1b;数据文件的物理文件名为‘C:\DA…

基于Java语言的培训平台+学习平台+在线学习培训系统+教育平台+教育学习系统+课程学习平台

简述 企业培训平台企业考试系统培训平台考试系统企业大学企业视频网站视频学习平台 介绍 企业培训平台支持企业培训考试全流程&#xff0c;在线学习、在线考试&#xff0c;成熟的企业培训考试解决方案&#xff0c;充分满足企业培训需求。 独立部署&#xff0c;仅内部员工登录…

【热门】智慧果园管理系统解决方案

随着科技的进步,原有农业种植方式已经不能满足社会发展的需要,必须对传统的农业进行技术更新和改造。经过多年的实践,人们总结出一种新的种植方法——温室农业,即“用人工设施控制环境因素,使作物获得最适宜的生长条件,从而延长生产季节,获得最佳的产出”。这种农业生产方式…

03.顺序表实现

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储&#xff0c;在数组上完成数据的增删改查。一般见到的顺序表都是在结构体中定义的数组&#xff0c;只是比普通数组多了增删改查等一些其他功能函数。 上节已经介绍了顺序表有…

【android studio】Gradle和Gradle插件版本关系/配置/常见ERR示例

参考链接&#xff1a; Android之Gradle和Gradle插件区别及联系 grdle 的安装与配置 、gradle和jdk版本对应关系 Android Gradle Plugin与Gradle版本、JDK版本对应关系 配置示例 常见err 主要原因 1.编译版本未设定 2.有多个module而且gradle 版本设置不一致 修改如下&#xf…

虚幻闪烁灯光材质

创建一个材质 材质域改成光照函数 , Time让材质动起来 参数B用来控制速度 , Sine 让灯光闪烁 , Frac 增加了闪烁细节 把材质放到灯光材质上 效果还是挺不错的! 可以用于一些恐怖游戏~

OpenCV高级图形用户界面(8)在指定的窗口中显示一幅图像函数imshow()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在指定的窗口中显示一幅图像。 函数 imshow 在指定的窗口中显示一幅图像。如果窗口是以 cv::WINDOW_AUTOSIZE 标志创建的&#xff0c;图像将以原…

仕考网:国考笔试没进面还有机会吗?

在国家公务员考试及各省公务员考试中&#xff0c;除了常规的招录程序之外&#xff0c;还有调剂、递补和补录多重机会。 调剂&#xff1a;于笔试结束之后至面试启动之前.针对因报名人数不足未达到预定面试比例的岗位&#xff0c;将开放公开调剂。只要考生的笔试成绩超越了国考设…

如何查看默认网关地址:详细步骤

在日常的网络配置与故障排查中&#xff0c;了解并正确查看默认网关地址是一项基础且至关重要的技能。默认网关是连接本地网络与外部网络&#xff08;如互联网&#xff09;的关键节点&#xff0c;它扮演着数据包转发的重要角色。无论是家庭网络、办公室网络还是更复杂的网络环境…

一些简单的编程题(Java与C语言)

引言&#xff1a; 这篇文章呢&#xff0c;小编将会举一些简单的编程题用来帮助大家理解一下Java代码&#xff0c;并且与C语言做个对比&#xff0c;不过这篇文章所出现的题目小编不会向随缘解题系列里面那样详细的讲解每一到题&#xff0c;本篇文章的主要目的是帮助小编和读者们…

vcenter的使用

1 配置 1.1 时间配置 报错原因&#xff1a;ESXI主机没有配置DNS无法解析NTP服务器网址。 解决办法&#xff1a;配置ESXI主机DNS&#xff0c;操作如下图。 点击【配置】、【服务】 【编辑启动策略】 我们可以看到当前的【NTP服务状态】处于 已停止的状态 点击【配置】、【时间…

基于直播美颜SDK的实时美颜平台开发指南

随着直播平台的快速发展&#xff0c;用户对视频质量的要求越来越高&#xff0c;尤其是对于美颜效果的需求。为满足这一市场需求&#xff0c;基于直播美颜SDK的实时美颜平台应运而生。本文将探讨如何开发这样一个平台&#xff0c;助力开发者在激烈的竞争中脱颖而出。 一、理解美…