前言
数学杂谈这个东西。。。我好像已经很久没有更新了吧。。。QwQ
当然,今天作为某道题的基础,这当然是必不可少的了。
各种表达式
一个式子能分成三种:前缀表达式,中缀表达式,后缀表达式。
正如其名,前缀表达式就是所有的符号都在前面;中缀表达式呢,就是我们平时用到的式子了;后缀表达式就是所有的运算符都在后面。
一般来说,计算机用到的都是前缀表达式和后缀表达式(反正不会是中缀就行了)
话说好奇怪啊,人类发明的东西,竟然不是按照人类的思维来做??
当然前缀和后缀有个好处,他们的式子中不可能会有括号存在。因为在这两个表达式中,在中缀优先的,这里也能优先,并且不需要括号来限制。
当然,这样说着很抽象,看个式子:
4
∗
5
+
4
∗
(
6
+
7
∗
(
2
+
3
−
5
)
)
∗
5
4 * 5 + 4 * (6 + 7 * (2 + 3 - 5)) * 5
4∗5+4∗(6+7∗(2+3−5))∗5,转换成后缀是这样的:
4
5
∗
4
6
7
2
3
+
5
−
∗
+
∗
5
∗
+
4 \ 5 * 4\ 6\ 7\ 2\ 3 + 5 - * + *\ 5 * +
4 5∗4 6 7 2 3+5−∗+∗ 5∗+,前缀就先放一边吧,今天主要是研究中缀转后缀。。。其实是我太蒟了 (逃
后缀表达式的机制呢就是碰到一个运算符后,在找他前面遇到的第 1 、 2 1、 2 1、2个数字,将其进行运算,然后再找下一个,直到表达式算完。
先贴一下后缀表达式计算的参考代码吧:
Code
#include<cstdio>
#include<stack>
#include<cstdlib>
using namespace std;
stack<int> a;
char s[10];
int x,y,z;
int main()
{
while(scanf("%s",s)==1)
if(s[0]>='0'&&s[0]<='9')
{
z=atoi(s);//将字符串转化为整形,atof是转化为浮点数
a.push(z);
}
else
{
x=a.top();
a.pop();
y=a.top();
a.pop();
switch(s[0])
{
case'+': a.push(x+y);break;
case'-': a.push(y-x);break;//因为先放进的是被减/除数,后放进的是减/除数,所以要倒过来
case'*': a.push(x*y);break;
case'/': a.push(y/x);break;
}
}
x=a.top();
printf("%d",x);
}
差不多就是这样,看得懂思路就行(我都觉得写得很稚嫩),毕竟是一年前写得嘛
怎么转换
这才是最重要的说
前面已经说了后缀表达式计算的机制了,那么接下来就来讲讲具体转换的步骤:
1. 如果说遇到的是数字的话,那么就可以直接输出,判断下一个
2. 如果说遇到的是左括号的话,先存进去等遇到右括号后再处理
3. 如果说遇到的是运算符的话,那么先存进栈,等碰到下一个运算符时在判断优先级的大小,左括号的优先级最低,加减次之,乘除最高(此处不考虑幂)。如果说栈里的那个运算符比当前这个运算符大的话,就说明可以优先输出栈里的了,用while循环判断,如果说栈里的优先级大于等于该运算符的话,就一直输出,否则将该运算符入栈
4. 如果说遇到的右括号的话,就说明这个括号里的运算操作都已经做完了,可以直接一股脑的将栈里左括号之后的输出就 O K OK OK了。
5. 如果说这个串读完了,而栈里还有的话,也就直接输出就可以了。还有一个注意是所有的括号均不输出。
Code
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <queue>
#include <stack>
#include <cstring>
#include <iostream>
using namespace std;
#define reg register
#define LL long long
#define INF 0x3f3f3f3f
template<typename T>
void re (T &x){
x = 0;
int f = 1;
char c = getchar ();
while (c < '0' || c > '9'){
if (c == '-') f = -1;
c = getchar ();
}
while (c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + c - 48;
c = getchar ();
}
x *= f;
}
template<typename T>
void pr (T x){
if (x < 0){
putchar ('-');
x = ~x + 1;
}
if (x / 10) pr (x / 10);
putchar (x % 10 + 48);
}
string A, B;
int lena;
stack<char> S;
int cmp (char s){
if (s == '(')
return 0;
else if (s == '+' || s == '-')
return 1;
else return 2;
}
void transfer (string A){
lena = A.length ();
for (int i = 0; i < lena; i++){
if (A[i] >= '0' && A[i] <= '9'){
int j;
for (j = i; j < lena && A[j] >= '0' && A[j] <= '9'; j++)
B += A[j];
B += ' ';
i = j - 1;
}
else if (A[i] == 'x'){
B += A[i];
B += ' ';
}
else if (A[i] == '(')
S.push (A[i]);
else if (A[i] == '+' || A[i] == '-' || A[i] == '*'){
if (S.empty ()){
S.push (A[i]);
continue;
}
int lev1 = cmp (A[i]), lev2 = cmp (S.top ());
if (lev1 > lev2) S.push (A[i]);
else{
while (!S.empty () && lev1 <= cmp (S.top ())){
B += S.top ();
B += ' ';
S.pop ();
if (!S.empty ())
lev2 = cmp (S.top ());
}
S.push (A[i]);
}
}
else{
while (S.top () != '('){
B += S.top ();
B += ' ';
S.pop ();
}
S.pop ();
}
}
while (!S.empty ()){
B += S.top ();
B += ' ';
S.pop ();
}
}
int main (){
cin >> A;
transfer (A);
cout << B << endl;
return 0;
}