【洛古 P1175】表达式的转换
表达式的转换
题目描述
平常我们书写的表达式称为中缀表达式,因为它将运算符放在两个操作数中间,许多情况下为了确定运算顺序,括号是不可少的,而后缀表达式就不必用括号了。
后缀标记法:书写表达式时采用运算紧跟在两个操作数之后,从而实现了无括号处理和优先级处理,使计算机的处理规则简化为:从左到右顺序完成计算,并用结果取而代之。
例如:8-(3+2*6)/5+4
可以写为:8 3 2 6 * + 5 / - 4 +
其计算步骤为:
8 3 2 6 * + 5 / - 4 +
8 3 12 + 5 / - 4 +
8 15 5 / - 4 +
8 3 - 4 +
5 4 +
9
编写一个程序,完成这个转换,要求输出的每一个数据间都留一个空格。
输入格式
就一行,是一个中缀表达式。输入的符号中只有这些基本符号 0123456789+-*/^()
,并且不会出现形如 2*-3
的格式。
表达式中的基本数字也都是一位的,不会出现形如 12
形式的数字。
所输入的字符串不要判错。
输出格式
若干个后缀表达式,第 i + 1 i + 1 i+1 行比第 i i i 行少一个运算符和一个操作数,最后一行只有一个数字,表示运算结果。
样例 #1
样例输入 #1
8-(3+2*6)/5+4
样例输出 #1
8 3 2 6 * + 5 / - 4 +
8 3 12 + 5 / - 4 +
8 15 5 / - 4 +
8 3 - 4 +
5 4 +
9
样例 #2
样例输入 #2
2^2^3
样例输出 #2
2 2 3 ^ ^
2 8 ^
256
提示
运算的结果可能为负数,/
以整除运算。并且中间每一步都不会超过 2 31 2^{31} 231。字符串长度不超过 100 100 100。
注意乘方运算 ^
是从右向左结合的,即 2 ^ 2 ^ 3
为 2 ^ (2 ^ 3)
,后缀表达式为 2 2 3 ^ ^
。
其他同优先级的运算是从左向右结合的,即 4 / 2 / 2 * 2
为 ((4 / 2) / 2) * 2
,后缀表达式为 4 2 / 2 / 2 *
。
保证不会出现计算乘方时幂次为负数的情况,故保证一切中间结果为整数。
解题思路
STEP 1:写出给定字符串的后缀表达式。
首先,我们要知道如何手算得出后缀表达式。下面是题目样例的后缀表达式转换方法。
那么如何用编程来实现呢?
我们定义一个函数来判断运算符的优先级。如下:
int check(char c)
{switch(c){case '+':return 1;case '-':return 1;case '*':return 2;case '/':return 2;case '^':return 3;case '(':return 0;case ')':return 0;default:return -1;//程序不会执行这句,保险起见要加上}
}
定义两个栈 dat 和 op,它们存的分别是后缀表达式和符号。
来看例子:2 + 3 * 4
这时,逆序输出栈 dat,得到式子的后缀表达式 2 3 4 * +。
再看一个:2 * 4 + 3
这时,逆序输出栈 d a t dat dat,得到式子的后缀表达式 2 4 * 3 +。
经过尝试和拼凑,我们发现: s i s_i si 为数字时,直接压进 d a t dat dat栈。 s i s_i si为运算符时,优先级若比 op 栈栈顶符号高(是 > > > 而不是 ≥ \ge ≥,可以自己模拟看看),就压进栈,否则就弹出 o p op op 的栈顶元素到 d a t dat dat 栈里,直到比栈顶符号优先级高或栈空。
最后,将 o p op op 栈里的剩余元素弹出到 d a t dat dat 栈。
特殊情况
(1)括号
当 s i s_i si为左括号时,可以直接压进 op 栈里。当 s i s_i si为右括号时,一直弹出 o p op op 栈栈顶到 d a t dat dat 里,直到栈顶为左括号,再弹出左括号。这些也可以通过模拟得出答案。
看例子:2 + (3 + 4) * 3
最后逆序输出 dat 栈,得到:2 3 4 + 3 * +
(2)乘方
特殊的乘方运算。模拟样例 2:2 ^ 2 ^ 3
我们得到:2 2 3 ^ ^
所以,当 s i s_i si为乘方运算符时且 o p op op 栈栈顶也是乘方运算符时,也可直接压进栈中。
表达式输出:
如果你用的是数组版栈,直接遍历即可。但如果你跟我一样用的是 STL 版栈,可以把栈 op 用来临时存放数据。先把 dat 里的元素全部压进 op 栈,输出字符,再倒回来。
STEP 2:写出计算过程。
为了方便,定义函数用来计算两个数的计算结果。
int js(char c){int p1=dat2.top();dat2.pop();int p2=dat2.top();dat2.pop();switch(c){case '+':return p2+p1;case '-':return p2-p1;case '*':return p2*p1;case '/':return p2/p1;case '^':return pow(p2,p1);default: return -0x3f3f3f3f; }
}
定义两个栈 n u m num num 与 d a t 2 , d a t 2 dat2,dat2 dat2,dat2 存储计算过程, n u m num num 用来临时存放数据,之前的 dat 和 op 可以继续使用。
把 d a t dat dat 全部弹出到 o p op op 里,接下来进行计算。
变量 t t t 获取 o p op op 栈顶, o p op op 弹出。
若 t 为数字,减去 ′ 0 ′ '0' ′0′ 再进入 d a t 2 dat2 dat2。若 t 为运算符,弹出 d a t 2 dat2 dat2 栈顶 2 个元素并记录,将运算结果压进栈,同时输出过程。
重复 1 和 2 两个步骤,直到 op 为空。
输出过程时,反序输出 d a t 2 dat2 dat2,正序输出 o p op op。
代码
#include<bits/stdc++.h>
#define ll long longusing namespace std;
char a[110],ans1[110];
int l,k1,k2;stack<int>num;
stack<char>dat;
stack<char>op;
stack<int>dat2;int check(char c){switch(c){case ')':return 0;case '(':return 0;case '+':return 1;case '-':return 1;case '*':return 2;case '/':return 2;case '^':return 3;default: return -1; }
}int js(char c){int p1=dat2.top();dat2.pop();int p2=dat2.top();dat2.pop();switch(c){case '+':return p2+p1;case '-':return p2-p1;case '*':return p2*p1;case '/':return p2/p1;case '^':return pow(p2,p1);default: return -0x3f3f3f3f; }
}void work1(){for(int i=1;i<=l;i++){if(a[i]>='0'&&a[i]<='9')dat.push(a[i]);else {if(op.empty()){op.push(a[i]);continue;}char c=op.top();if(a[i]=='('){ op.push(a[i]);continue;}if(a[i]==')'){while(c!='('&&!op.empty()){dat.push(c);op.pop(); if(!op.empty()) c=op.top();}op.pop();continue;}if(check(a[i])>check(c)){op.push(a[i]);}else{if(check(a[i])==check(c)&&check(a[i])==3){op.push(a[i]);continue;}while(check(a[i])<=check(c)&&!op.empty()){dat.push(c);op.pop(); if(!op.empty()) c=op.top();}op.push(a[i]);}}}while(!op.empty()){dat.push(op.top()); op.pop();}while(!dat.empty()){op.push(dat.top()); dat.pop();} while(!op.empty()){char c=op.top();cout<<c<<' ';op.pop();dat.push(c);}cout<<endl;
}void work2(){while(!dat.empty()){char t=dat.top();dat.pop();op.push(t);}while(!op.empty()){char c=op.top();if(c>='0'&&c<='9'){dat2.push(c-'0');op.pop();}else {dat2.push(js(c)); op.pop();while(!dat2.empty()){num.push(dat2.top()); dat2.pop();}while(!num.empty()){cout<<num.top()<<' ';dat2.push(num.top());num.pop(); }while(!op.empty()){cout<<op.top()<<' '; dat.push(op.top()); op.pop();}while(!dat.empty()){op.push(dat.top()); dat.pop();}cout<<endl;}}
}int main(){scanf("%s",a+1);l=strlen(a+1);work1();work2();
}
【洛古 P1175】表达式的转换相关推荐
- 【Python】洛谷 P1175_表达式的转换(逆波兰式、中缀表达式、后缀表达式、栈)
目录 题目 代码 AC截图 题目 代码 碎碎念:我用来复习栈的,刷了巨长时间,一直Runtine Error,编译直接就没有过. 好家伙,然后发现是数据给的不够严谨,左右两端有空格,使用strip() ...
- 贤鱼的刷题日常(数据结构栈学习)--P1175 表达式的转换--题目详解
- 洛古最简单50题解(31-40)
做为一名新手,首先要过一过题,找找成就感.(大佬略过).下面附上洛古最简单50题(大佬略过).以及最麻烦 AC代码,至少AC了. 目录·列表: 洛古最简单50题解(1-10) 洛古最简单50题解(11 ...
- R语言parse函数、deparse函数、expression函数实现字符串和表达式的转换实战
R语言parse函数.deparse函数.expression函数实现字符串和表达式的转换实战 目录 R语言parse函数.deparse函数.expression函数实现字符串和表达式的转换实战
- 天勤数据结构:前缀、中缀、后缀表达式的转换与计算
第三章 栈和队列 1. 输出队列问题 2. 表达式的转换 - 手工转换 2.1 中缀表达式 转 前缀表达式 2.2 中缀表达式 转 后缀表达式 2.3 后缀表达式 转 中缀表达式 2.4 后缀表达式 ...
- matlab状态方程 传递函数 可控性,实验一matlab系统的传递函数和状态空间表达式的转换...
实验一 MATLAB 系统的传递函数和状态空间表达式的转换 一. 实验目的 1.学习多变量系统状态空间表达式的建立方法: 2.通过编程.上机调试,掌握多变量系统状态空间表达式与传递函数之间相互转换的方 ...
- [深入学习C#]LINQ查询表达式详解(2)——查询表达式的转换
转载自诗人江湖老,原文地址 C#在执行LINQ查询表达式的时候,并不会指定其执行语义,而是将查询表达式转换为遵循查询表达式模式的方法的调用.具体而言,查询表达式将转换为以下名称的调用:Where.Se ...
- 二叉树:表达式二叉树转换成中缀式(括弧处理)
文章目录 问题描述 : 输入说明 : 输出说明 : 输入范例 : 输出范例 : 思路分析 代码实现 事故现场 第一次提交 分析与总结 如果不妥请留言,你的关注和回复是对我最大的鼓励,谢谢!如果想立即回 ...
- 【洛古 P8815】[CSP-J 2022] 逻辑表达式
[CSP-J 2022] 逻辑表达式 题目描述 逻辑表达式是计算机科学中的重要概念和工具,包含逻辑值.逻辑运算.逻辑运算优先级等内容. 在一个逻辑表达式中,元素的值只有两种可能: 0 0 0(表示假) ...
最新文章
- android约束布局中 链,Android-ConstraintLayout(约束布局)-Chains链(链条布局,Nice)
- ckeditor5加字数_CKEditor5基本使用
- Dapper源码学习和源码修改
- sql where in 排序问题
- SQL Server之备份和还原系统数据库
- pythonserial函数_python3.5 中serial模块的问题
- mac的rubywoo怎么读_macrubywoo是几号
- proxy ip 收集方式总结
- 厦门市大专计算机学校有哪些,2021厦门公办大专学校有哪些 【教育部专科院校名单】...
- CSAPP家庭作业答案7 8 9章
- 算法描述---伪代码
- android开发方法数,Android方法数methods超过65536详解
- Sqlite 索引的使用、索引的优缺点
- 打孔的问题和打孔的位置
- 相机ISP图像处理流程
- win10修改用户名导致问题及解决
- ios 隐私政策网址(URL)
- BGP路由选路与负载
- CentOS7 忘记登陆密码 修改root密码
- ProGuard的作用
热门文章
- aosp编译设备树文件dtbo.img
- SAP中采购合同和计划协议类型默认值的设定实例
- matlab画邦加球,一种测量应力方向的光纤传感器的制作方法
- 图片 频率域 matlab_时间域电磁法勘探的正演问题研究
- 报错expected statement
- 服务器安装centos6
- 2036 改革春风吹满地
- mysql1808_mysql表空间传输(ERROR 1808) row_format设置 翰墨文海
- 协变(covariance),逆变(contravariance)与不变(invariance)
- ureport2下载EXCEL报错:org/apache/poi/POIXMLTypeLoader