双栈完全解决计算器问题
文章目录
- 题目
- 题目分析
- 代码拆解
- 预处理
- 关键求值函数calc()
- 括号处理
- 数字和字符处理
- 综合代码得出答案
题目
我就口头描述一遍吧:把给出的表达式字符串计算它的算式结果并返回。其中表达式只含有:’+’、’-’、’*’、’/’、空格、数字。。。这些字符。
而对于表达式可能会出现:3+(2*-2) or 7+(-34+5)..
等特殊情况。
题目分析
对于这种算式计算我们一般采用双栈形式:
- 数字处理栈:用于存储表达式中的数字。
- 字符处理栈:用于存储各种运算符以及括号。
而我们如何处理这样一个计算过程呢?
- 预处理(去空格、数字栈预先置0、设置优先级、设置正负标记)
- 扫描到括号:
'('
则入栈,碰到')'
则开始出栈计算答案,直到遇到左括号。 - 扫描到数字或者字符:
对于数字,一旦扫描到一个数字的开头,就一直连续扫描到结尾进行数字更新,最后的结果再乘以符号标记。
对于字符,一旦扫描到字符后,字符串的前一个仍然是字符,则该字符只可能是代表数字的符号,所以此字符不入栈,仅仅作为更新数字符号的标记,其他情况就根据优先级判断上一个运算符的优先级是否大于等于当前的运算符,如果是,则开始计算答案。
如果到最后字符栈还有运算符则继续计算,直到为空
代码拆解
预处理
去空格
void preCond(string& s){int i = s.find(' ');while(i!=-1){s.replace(i,1,"");i = s.find(' ');}}
置0,设置优先级和符号标记(默认为正)
nums.push_back(0);prior['+'] = prior['-'] = 1;prior['*'] = prior['/'] = 2;int syb = 1;
关键求值函数calc()
int calc(){int b = nums.back();nums.pop_back();int a = nums.back();nums.pop_back();char op = ops.back();ops.pop_back();switch(op){case '+':return a+b;case '-':return a-b;case '*':return a*b;case '/':return a/b;}return -1;}
括号处理
//括号处理if(op=='(') ops.push_back(op);else if(op==')'){while(!ops.empty()){if(ops.back()!='(')nums.push_back(calc());else {ops.pop_back();break;}}}
数字和字符处理
//数字和符号处理(碰到强行2*-3的情况,直接在入数字的时候入-3,符号'-'不要计入符号栈)else{if(isdigit(op)){int j = i;int num = 0;while(isdigit(s[j])){num = num*10 + (s[j++]-'0');}nums.push_back(num*syb);syb = 1;i = j-1;}else{if(i>0&& s[i-1]=='(' or s[i-1]=='*' or s[i-1]=='/' or s[i-1]=='+' or s[i-1]=='-'){if(op=='-')syb = -1;}else{while(!ops.empty()&&prior[ops.back()]>=prior[op]){nums.push_back(calc());}ops.push_back(op);}}}}while(!ops.empty()){nums.push_back(calc());}
综合代码得出答案
还好效率还行!
class Solution {public:int calculate(string s) {//预处理三件事:1.消除空格 2.防止最开始有符号设置了最开始0入栈 3.用数组设置优先级preCond(s);nums.push_back(0);prior['+'] = prior['-'] = 1;prior['*'] = prior['/'] = 2;int syb = 1;for(int i=0;i<s.size();i++){char op = s[i];//括号处理if(op=='(') ops.push_back(op);else if(op==')'){while(!ops.empty()){if(ops.back()!='(')nums.push_back(calc());else {ops.pop_back();break;}}}//数字和符号处理(碰到强行2*-3的情况,直接在入数字的时候入-3,符号'-'不要计入符号栈)else{if(isdigit(op)){int j = i;int num = 0;while(isdigit(s[j])){num = num*10 + (s[j++]-'0');}nums.push_back(num*syb);syb = 1;i = j-1;}else{if(i>0&& s[i-1]=='(' or s[i-1]=='*' or s[i-1]=='/' or s[i-1]=='+' or s[i-1]=='-'){if(op=='-')syb = -1;}else{while(!ops.empty()&&prior[ops.back()]>=prior[op]){nums.push_back(calc());}ops.push_back(op);}}}}while(!ops.empty()){nums.push_back(calc());}return nums.back();}
private:int prior[128] = {0};vector<int>nums;vector<char>ops;int calc(){int b = nums.back();nums.pop_back();int a = nums.back();nums.pop_back();char op = ops.back();ops.pop_back();switch(op){case '+':return a+b;case '-':return a-b;case '*':return a*b;case '/':return a/b;}return -1;}void preCond(string& s){int i = s.find(' ');while(i!=-1){s.replace(i,1,"");i = s.find(' ');}}
};
```
双栈完全解决计算器问题相关推荐
- Leetcode224 基本加减计算器-双栈和状态转换
题目 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 . 示例 1: 输入: "1 + 1&quo ...
- P1155 双栈排序(二分图的染色判断+链式前向星)
P1155 双栈排序 让字典序最小,当然尽量进S1 那什么时候必须进S2呢? a[i]和a[j] 不能压入同一个栈⇔存在一个k,使得i<j<k且a[k]<a[i]<a[j] 因 ...
- P1155 双栈排序(二分图染色)
P1155 双栈排序(二分图染色) 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一 ...
- 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)
虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...
- 双栈(Dual Stack)
双栈(Dual Stack) 1. 双栈的概念 1.1 双栈的定义 双栈是指两个顺序栈,是一种特殊的顺序栈. 1.2 双栈中各元素的逻辑及存储关系 双栈共享一个地址连续的存储单元.即程序同时需要两个栈 ...
- 双栈排序java_双栈排序
23 思路: 1.先看下图 初始栈initStack中存放的数组中待排序的数:临时栈tempStack中存放的是已经排好序的数. 现在继续对初始栈中的数进行排序,5应当插入到临时栈哪个位置? 2. 5 ...
- 双栈路由Linux,Linux模拟IPV6双栈路由器实现方案
介绍了IPV6的网络路由器的原理和在Linux上的具体实现方法.讨论了在Linux下如何搭建IPV6网络试验平台,重点讨论如何将Linux工作站模拟成双栈路由器.然后介绍了静态路由和动态RIPng路由 ...
- ipv4v6双栈技术_【第二十六期】IPv6系列应用篇——数据中心IPv4/IPv6双栈架构探讨...
背景 2017年,工业和信息化部发布了<推进互联网协议第六版(IPv6)规模部署行动计划>的通知,从国家层面推动下一代IP技术--IPv6的普及和应用.目标到2020年末,IPv6活跃用户 ...
- ipv4v6双栈技术_IPv6过渡技术之双栈技术
IPv6经过20多年的发展研究实验,已经成为一项成熟技术,其具有大量IP地址数量.更小路由表.更安全等特点,为有效解决IPv4现存问题提供了途径.但是由于IPv6本身与IPv4不兼容,在IPv6成为主 ...
最新文章
- linux rsync
- java enumerable_java - Java相当于C#的'Enumerable.Any' - 堆栈内存溢出
- linux 线程_浅谈Linux线程模型
- 【DP】【容斥】Nice to Meet You(AT3634)
- Java核心技术点之反射
- 如何格式化128GU盘为fat32?
- centos安装aria2c_CentOS下安装aria2教程
- k_fold_cv函数——bartMachine包内函数详解
- 一位业内人士关于奶粉各品牌的评价(转载)
- html鼠标经过图片有浮起效果,CSS实现鼠标滑过卡片上浮效果的示例
- 懂电脑的都不会买i7处理器,程序员:我有一个十几万的电脑梦
- 关于RxJava2.0你不知道的事
- 【SAMMY】DOS下操作隐藏文件、文件夹
- Codeforces 32C.Flea
- Python查询mysql返回序列化数据
- linux红帽子安装驱动,安装红帽子使用有megaSR swraid驱动程序和OS推进指点的嵌入式SATA控制器常见设备使用情况的...
- Android RenRen SDK 接入教程
- 酷狗音乐关键字搜索并生成下载url
- 手动Docker部署saber
- android壁纸 镭光,Blur Wallpaper
热门文章
- 从0和1开始,揭开数字世界的神秘面纱
- iphoneX系列手机在页面滚动时隐藏底部的操作栏
- 运动都需要什么装备?运动锻炼必备物品推荐
- 接口开发任务完成中(待续)
- python计算存款复利计算器_分享下自己写的计算余额宝上复利的代码,网上的复利计算器无法满足需求...
- 一支笔的测试点_.一支杯子和一支笔的测试用例
- 大学在校 计算机考试,大学必考证书 | 计算机考试报名要开始啦!
- 【转】unity 的 MonoDevelop 在Windows下显示中文不出现乱码
- STATA 森林图 基于OR值和CI直接画的
- [读后感] 书名:追风筝的人