C++ stack和queue模拟实现

目录

    • stack
    • 习题练习
      • 逆波兰表达式求值
      • 基本计算器
    • stack模拟实现
    • queue
    • queue模拟实现
    • deque了解
    • priority_queue
    • priority_queue模拟实现
    • 仿函数

stack

在这里插入图片描述
stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。

stack的使用(最常用的):
在这里插入图片描述

习题练习

逆波兰表达式求值

在这里插入图片描述
思路:
遇到操作数就入栈
遇到操作符就取栈顶的两个操作数运算,结果再入栈

class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;for(auto str:tokens){if(str=="+"|| str=="-"|| str=="*"|| str=="/"){//出栈中操作数进行运算int right=st.top();st.pop();int left=st.top();st.pop();switch(str[0]){case '+':st.push(left+right);break;case '-':st.push(left-right);break;case '*':st.push(left*right);break;case '/':st.push(left/right);break;}}else{st.push(stoi(str));}}return st.top();}
};

基本计算器

思路:
在这里插入图片描述

class Solution {
public:int pre(char ch)//优先级判断{if(ch=='+'|| ch=='-')return 1;else if(ch=='(' || ch==')')return 3;else//如果有*/return 2;}int calculate(string s) {vector<int> v;stack<char> st;int i=0;for(int i=0;i<s.size();i++){if(isdigit(s[i]))//遇到操作数放到vector里{string s1;while(isdigit(s[i])){s1+=s[i++];}i--;v.push_back(stoi(s1));//如果遇到是-1if(v.size()==st.size()==1){v.pop_back();st.pop();v.push_back(-stoi(s1));}}else if(s[i]!=' ')//遇到操作符{if(s[i]=='('){//递归解决string tmp(s,i+1);v.push_back(calculate(tmp));//找到)i++;int count=1;//代表1个(,对应着一个),如果在找的过程中发现了第二个(,count++while(count!=0){if(s[i]=='('){count++;}else if(s[i]==')'){count--;}if(count!=0)i++;}//递归解决完之后,面临和上面遇到-1一样的情况if(v.size()==st.size()==1){int a=v.back();v.pop_back();st.pop();v.push_back(-a);}continue;}if(s[i]==')'){break;}while(!st.empty()){char top=st.top();//ch运算符优先级比top高,入栈if(pre(s[i])>pre(top)){st.push(s[i]);}else{_operator(st,v);}}if(st.empty()){st.push(s[i]);}}}while(!st.empty()){_operator(st,v);}return v.back();}void _operator(stack<char>& st,vector<int>& v)//出栈顶操作符对两个操作数运算然后将结果放回vector{char top=st.top();//出栈顶元素st.pop();int right=v.back();v.pop_back();int left=v.back();v.pop_back();//运算v中数据把结果放回去switch(top){case'+':v.push_back(left+right);break;case'-':v.push_back(left-right);break;}}};

stack模拟实现

namespace st
{template<class T,class Container = deque<T>>//不管Container这个底层容器是谁,都可以适配栈class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}const T& top(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
};void test_stack()
{st::stack<int, vector<int>> v;v.push(1);v.push(3);v.push(2);v.push(7);v.push(5);while (!v.empty()){cout << v.top() << " ";v.pop();}cout << endl;
}int main()
{test_stack();return 0;
}

queue

在这里插入图片描述

队列是一种容器适配器,先进先出,其中从容器一端插入元素,另一端提取元素。

queue模拟实现

queue的接口中存在头删和尾插,因此使用vector来封装效率太低,可以借助list来模拟实现queue

namespace q
{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;};
};void test_queue()
{q::queue<int, list<int>> q;q.push(4);q.push(3);q.push(2);q.push(9);q.push(5);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;
}int main()
{test_queue();return 0;
}

deque了解

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。

选deque是因为:

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

priority_queue

在这里插入图片描述
优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成
堆的结构,因此priority_queue就是堆

默认的Compare是less,也就是大堆
想创建的是小堆,可以用greater

priority_queue<int,vector<int>,greater<int>> q

使用sort和priority_queue时参数是不同的
在这里插入图片描述

priority_queue模拟实现

#include<iostream>
#include<vector>
#include<queue>
using namespace std;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 my_pq
{template<class T,class Comtainer = vector<T>,class Compare = Less<T>>class priority_queue{public:priority_queue(){}//根据迭代器区间初始化template<class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first, last){//向下调整size_t n = _con.size();for (size_t i = (n - 2) / 2; i >= 0; i--){adjust_down(i);}}void adjust_up(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){//if (_con[parent] < _con[child])if (com(_con[parent],_con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjust_down(int parent){Compare com;int child = parent * 2 + 1;size_t n = _con.size();while (child < n){//if (child + 1 < n//	&& _con[child] < _con[child + 1])if (child + 1 < n&& com(_con[child], _con[child + 1])){++child;}//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);//向上调整,传child}void pop(){swap(_con[0],_con[_con.size()-1]);//交换堆顶到末尾再删除_con.pop_back();adjust_down(0);//向下调整,传parent}const T& top(){return _con[0];}bool empty(){return _con.empty();}private:Comtainer _con;};
}
int main()
{//my_pq::priority_queue<int> q;my_pq::priority_queue<int,vector<int>,Greater<int>> q;q.push(2);q.push(1);q.push(5);q.push(3);while (!q.empty()){cout << q.top() << " ";q.pop();}return 0;
}

仿函数

在模拟实现优先级队列的时候,priority_queue是大堆还是小堆取决于比较方法,可以用函数指针,但函数指针可读性不是很好,为了替代函数指针,仿函数就是个好方法
在这里插入图片描述

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

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

相关文章

修炼k8s+flink+hdfs+dlink(三:安装dlink)

一&#xff1a;mysql初始化。 mysql -uroot -p123456 create database dinky; grant all privileges on dinky.* to dinky% identified by dinky with grant option; flush privileges;二&#xff1a;上传dinky。 上传至目录/opt/app/dlink tar -zxvf dlink-release-0.7.4.t…

asp.net饭店订餐管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio计算机设计定制

一、源码特点 asp.net 饭店订餐管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 asp.net饭店订餐系统 二、功能介…

HTML5开发实例-3D全景(ThreeJs全景Demo) 详解(图)

前言 在现在市面上很多全景H5的环境下,要实现全景的方式有很多,可以用css3直接构建也可以用基于threeJs的库来实现,还有很多别的制作全景的软件使用 本教学适用于未开发过3D全景的工程狮 如果觉得内容太无聊可以直接跳到最后 下载代码 理论 整个3D全景所用的相关理论就…

知识增强语言模型提示 零样本知识图谱问答10.8

知识增强语言模型提示 零样本知识图谱问答 摘要介绍相关工作方法零样本QA的LM提示知识增强的LM提示与知识问题相关的知识检索 摘要 大型语言模型&#xff08;LLM&#xff09;能够执行 零样本closed-book问答任务 &#xff0c;依靠其在预训练期间存储在参数中的内部知识。然而&…

在React中,什么是props(属性)?如何向组件传递props?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

QTableWidget 表格增删数据

QTableWidgetQTableWidgetQTableWidget部分使用方法&#xff0c;如在表格中插入或删除一行数据以及清空表格数据等。在添加数据时&#xff0c;设置了条件判断如正则表达式&#xff0c;若用户输入的数据不合法&#xff0c;则添加失败并提示用户错误的地方&#xff0c;便于用户修…

API接口安全运营研究(内附官方开发平台api接口接入方式)

摘 要 根据当前API技术发展的趋势&#xff0c;从实际应用中发生的安全事件出发&#xff0c;分析并讨论相关API安全运营问题。从风险角度阐述了API接口安全存在的问题&#xff0c;探讨了API检测技术在安全运营中起到的作用&#xff0c;同时针对API安全运营实践&#xff0c;提出…

Day 4 C++

算术运算符重载 种类&#xff1a; - * / % #include <iostream>using namespace std;class Cacu {friend const Cacu operator(const Cacu &l,const Cacu &r);friend const Cacu operator-(const Cacu &l,const Cacu &r);friend const Cacu operator*…

mysql面试题32:MySQL数据库服务器性能分析的方法命令有哪些?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:MySQL数据库服务器性能分析的方法命令有哪些? MySQL数据库服务器性能分析的方法和命令有以下几种: EXPLAIN命令:用于分析查询语句的执行计划,…

PHP Discord获取频道消息功能实现

PHP Discord获取频道消息功能实现 1. 关注对应频道2. 添加机器人3. 配置机器人权限4. 使用 DiscordPHP 类库5. 代码示例 (Laravel 框架)6. 服务器部署 1. 关注对应频道 首先要创建自己的频道, 然后到对应的公告频道中关注这个频道(这时 Discord 会让你选择频道, 选择之前创建的…

数据治理的核心是什么?_光点科技

数据治理是当今数字化时代中企业管理的关键组成部分。在信息爆炸的时代&#xff0c;企业积累了大量的数据&#xff0c;这些数据不仅是企业宝贵的资产&#xff0c;也是推动业务决策和创新的重要驱动力。数据治理的核心在于建立有效的框架和流程&#xff0c;以确保数据的质量、安…

经典面试题第十更---instanceof与typeof

前言&#xff1a; &#x1f921; 作者简介&#xff1a;我是Morning&#xff0c;计算机的打工人&#xff0c;想要翻身做主人 &#x1f648; &#x1f648; &#x1f648; &#x1f3e0; 个人主页&#xff1a; Morning的主页 &#x1f4d5;系列专栏&#xff1a; 前端…

uniapp vue3 静态图片引入

方法一 从新定义路径 一定看好你图片的路径 代码 <template><div class"main">Main<img :src"getImg()" alt""></div> </template><!-- 方式一 // <script setup> // let imgName logo.png // cons…

深度学习DAY3:FFNNLM前馈神经网络语言模型

1 神经网络语言模型NNLM的提出 文章&#xff1a;自然语言处理中的语言模型预训练方法&#xff08;ELMo、GPT和BERT&#xff09; https://www.cnblogs.com/robert-dlut/p/9824346.html 语言模型不需要人工标注语料&#xff08;属于自监督模型&#xff09;&#xff0c;所以语言…

[架构之路-235]:目标系统 - 纵向分层 - 数据库 - 数据库系统基础与概述:数据库定义、核心概念、系统组成

目录 一、核心概念 1.1 什么是数据与信息 1.2 数据与数据库的关系 1.3 什么是数据库 1.4 数据库中的数据的特点 1.5 数据库与数据结构的关系 二、数据库系统 2.1 什么是数据库管理系统 2.2 什么是数据库系统 2.3 数据库相关的人员 2.4 数据库的主要功能 2.5 Excel表…

【计算机网络-自顶向下方法】应用层(SMTP、POP3、DNS)

目录 1. Electronic Mail电子邮件应用画像1.1 电子邮件系统1.2 邮件报文格式1.3 邮件访问 2. DNS&#xff08;Domain Name System&#xff09;2.1 DNS提供的服务2.2 DNS工作机理2.3 DNS资源记录2.4 DNS协议&#xff0c;报文2.5 小结 1. Electronic Mail 电子邮件应用画像 应用…

企业如何使用CRM客户管理系统全面了解客户

B2B业务由于决策链长&#xff0c;涉及的部门和人员多&#xff0c;购买周期短则2、3个月&#xff0c;长则一年半载的原因一直被大家痛呼难做。B2B业务要求企业去认识客户&#xff0c;更要深入地了解客户。基于这种需求&#xff0c;使用CRM客户管理系统是企业全面了解客户的重要手…

Zabbix第二部分:基于Proxy分布式部署实现Web监控和Zabbix HA集群的搭建

代理和高可用 一、基于zabbix-proxy的分布式监控1.1 分布式监控的作用1.2 数据流向1.3 构成组件 二、部署zabbix代理服务器Step1 前置准备Step2 设置 zabbix 的下载源&#xff0c;安装 zabbix-proxyStep3 部署数据库并将zabbix相关文件导入Step4 修改zabbix-proxy的配置文件&am…

【排序算法】选择排序

文章目录 一&#xff1a;基本介绍1.1 概念1.2 算法思想1.3 思路分析图1.4 思路分析1.5 总结1.5.1 选择排序一共有数组大小-1轮排序1.5.2 每一轮排序&#xff0c;又是一个循环&#xff0c;循环的规则如下&#xff08;在代码中实现&#xff09;&#xff1a; 二&#xff1a;代码实…

VueRouter与expres/koa中间件的关联

ueRouter: runQueue 路由守卫都是有三个参数to,from,next。其中next就是下方的fn执行时候传入的第二个参数(回调函数)&#xff0c;只有该回调执行后才会挨个遍历queue内的守卫。 中间件的作用 隔离基础设施与业务逻辑之间的细节。详细的内容位于《深入浅出Node.js》P210 另外一…