表达式的转换

题目描述

平常我们书写的表达式称为中缀表达式,因为它将运算符放在两个操作数中间,许多情况下为了确定运算顺序,括号是不可少的,而后缀表达式就不必用括号了。

后缀标记法:书写表达式时采用运算紧跟在两个操作数之后,从而实现了无括号处理和优先级处理,使计算机的处理规则简化为:从左到右顺序完成计算,并用结果取而代之。

例如: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 ^ 32 ^ (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】表达式的转换相关推荐

  1. 【Python】洛谷 P1175_表达式的转换(逆波兰式、中缀表达式、后缀表达式、栈)

    目录 题目 代码 AC截图 题目 代码 碎碎念:我用来复习栈的,刷了巨长时间,一直Runtine Error,编译直接就没有过. 好家伙,然后发现是数据给的不够严谨,左右两端有空格,使用strip() ...

  2. 贤鱼的刷题日常(数据结构栈学习)--P1175 表达式的转换--题目详解

  3. 洛古最简单50题解(31-40)

    做为一名新手,首先要过一过题,找找成就感.(大佬略过).下面附上洛古最简单50题(大佬略过).以及最麻烦 AC代码,至少AC了. 目录·列表: 洛古最简单50题解(1-10) 洛古最简单50题解(11 ...

  4. R语言parse函数、deparse函数、expression函数实现字符串和表达式的转换实战

    R语言parse函数.deparse函数.expression函数实现字符串和表达式的转换实战 目录 R语言parse函数.deparse函数.expression函数实现字符串和表达式的转换实战

  5. 天勤数据结构:前缀、中缀、后缀表达式的转换与计算

    第三章 栈和队列 1. 输出队列问题 2. 表达式的转换 - 手工转换 2.1 中缀表达式 转 前缀表达式 2.2 中缀表达式 转 后缀表达式 2.3 后缀表达式 转 中缀表达式 2.4 后缀表达式 ...

  6. matlab状态方程 传递函数 可控性,实验一matlab系统的传递函数和状态空间表达式的转换...

    实验一 MATLAB 系统的传递函数和状态空间表达式的转换 一. 实验目的 1.学习多变量系统状态空间表达式的建立方法: 2.通过编程.上机调试,掌握多变量系统状态空间表达式与传递函数之间相互转换的方 ...

  7. [深入学习C#]LINQ查询表达式详解(2)——查询表达式的转换

    转载自诗人江湖老,原文地址 C#在执行LINQ查询表达式的时候,并不会指定其执行语义,而是将查询表达式转换为遵循查询表达式模式的方法的调用.具体而言,查询表达式将转换为以下名称的调用:Where.Se ...

  8. 二叉树:表达式二叉树转换成中缀式(括弧处理)

    文章目录 问题描述 : 输入说明 : 输出说明 : 输入范例 : 输出范例 : 思路分析 代码实现 事故现场 第一次提交 分析与总结 如果不妥请留言,你的关注和回复是对我最大的鼓励,谢谢!如果想立即回 ...

  9. 【洛古 P8815】[CSP-J 2022] 逻辑表达式

    [CSP-J 2022] 逻辑表达式 题目描述 逻辑表达式是计算机科学中的重要概念和工具,包含逻辑值.逻辑运算.逻辑运算优先级等内容. 在一个逻辑表达式中,元素的值只有两种可能: 0 0 0(表示假) ...

最新文章

  1. android约束布局中 链,Android-ConstraintLayout(约束布局)-Chains链(链条布局,Nice)
  2. ckeditor5加字数_CKEditor5基本使用
  3. Dapper源码学习和源码修改
  4. sql where in 排序问题
  5. SQL Server之备份和还原系统数据库
  6. pythonserial函数_python3.5 中serial模块的问题
  7. mac的rubywoo怎么读_macrubywoo是几号
  8. proxy ip 收集方式总结
  9. 厦门市大专计算机学校有哪些,2021厦门公办大专学校有哪些 【教育部专科院校名单】...
  10. CSAPP家庭作业答案7 8 9章
  11. 算法描述---伪代码
  12. android开发方法数,Android方法数methods超过65536详解
  13. Sqlite 索引的使用、索引的优缺点
  14. 打孔的问题和打孔的位置
  15. 相机ISP图像处理流程
  16. win10修改用户名导致问题及解决
  17. ios 隐私政策网址(URL)
  18. BGP路由选路与负载
  19. CentOS7 忘记登陆密码 修改root密码
  20. ProGuard的作用

热门文章

  1. aosp编译设备树文件dtbo.img
  2. SAP中采购合同和计划协议类型默认值的设定实例
  3. matlab画邦加球,一种测量应力方向的光纤传感器的制作方法
  4. 图片 频率域 matlab_时间域电磁法勘探的正演问题研究
  5. 报错expected statement
  6. 服务器安装centos6
  7. 2036 改革春风吹满地
  8. mysql1808_mysql表空间传输(ERROR 1808) row_format设置 翰墨文海
  9. 协变(covariance),逆变(contravariance)与不变(invariance)
  10. ureport2下载EXCEL报错:org/apache/poi/POIXMLTypeLoader