【题目链接】
ybt 1331:【例1-2】后缀表达式的值
【题目考点】
1. 表达式求值
2. 表达式树
表达式树:一棵表达式树可以表示一系列的运算。 表达式树中的结点包括运算符与数值
struct Node
{
char c;
int n;
}
- 分支结点:c:运算符,n:该子树对应的表达式的值
- 叶子结点:c:
'\0' ,n:数值 表达式树的值,是左子树的值和右子树的值,经过根结点运算符运算后得到的结果。
【解题思路】
题目中说参与运算的整数及结果的绝对值均在
2
64
2^{64}
264范围内,意思指的就是数据类型要设为long long。 (虽说
2
6
3
2^63
263及更大的数字不能用long long正确表示,但题目中实际上没有这么大的数字,用long long即可。)
解法1:后缀表达式直接求值
- 从左向右扫描后缀表达式。
- 遇到数字时,将数字入栈。
- 遇到运算符时,弹出栈顶的两个数,用该运算符对它们做相应的计算,结果入栈。
- 扫描结束后,栈顶数字就是结果。
解法2:后缀表达式构造表达式树
- 如果读到数字,那么新建数字结点入栈。
- 如果读到运算符,则新建运算符结点np,出栈两个结点,将这两个结点的值通过np的运算符运算后得到的值存为新结点np的值,将np入栈。
- 读完整个后缀表达式,栈中应该只剩1个结点,该结点就是表达式树的根结点,该结点的值就是表达式的值 。
解法3:递归
先将字符串处理为由结构体对象构成的后缀表达式,每个结构体对象可能是数字可能是运算符。 后缀表达式的结构为:<第一个运算单元><第二个运算单元><运算符> 每个运算单元也许是一个数字,也许是一个后缀表达式。 后缀表达式数组最后一个元素的下标为p。 设函数solve() ,求从第p位置开始向左遍历取到的第一个运算单元的值。每取一个元素,p向左移动一个位置。
- 如果p位置是数字,直接返回这个数字的值。
- 如果p位置是运算符,那么从p位置开始向左取两个运算单元的值,并用当前位置的运算符进行计算,得到这一运算单元的值。
【题解代码】
解法1:后缀表达式直接求值
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
stack<LL> stk;
LL calc(LL a, LL b, char c)
{
switch(c)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
case '/':
return a/b;
}
}
int main()
{
char s[260];
LL num = 0;
cin.getline(s, 260);
for(int i = 0; s[i] != '@'; ++i)
{
if(s[i] >= '0' && s[i] <= '9')
num = num * 10 + (s[i] - '0');
else if(s[i] == ' ')
{
stk.push(num);
num = 0;
}
else
{
LL b = stk.top();
stk.pop();
LL a = stk.top();
stk.pop();
stk.push(calc(a, b, s[i]));
}
}
cout << stk.top();
return 0;
}
解法2:后缀表达式构造表达式树
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct Node
{
char c;
LL n;
int left, right;
};
Node node[300];
int p;
stack<int> stk;
LL calc(LL a, LL b, char c)
{
switch(c)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
case '/':
return a/b;
}
}
int main()
{
char s[260];
LL num = 0;
cin.getline(s, 260);
for(int i = 0; s[i] != '@'; ++i)
{
if(s[i] >= '0' && s[i] <= '9')
num = num * 10 + (s[i] - '0');
else if(s[i] == ' ')
{
node[++p].n = num;
stk.push(p);
num = 0;
}
else
{
int pb = stk.top();
stk.pop();
int pa = stk.top();
stk.pop();
node[++p].c = s[i];
node[p].n = calc(node[pa].n, node[pb].n, node[p].c);
node[p].left = pa, node[p].right = pb;
stk.push(p);
}
}
int root = stk.top();
cout << node[root].n;
return 0;
}
解法3:递归
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct Node
{
char c;
LL n;
};
Node eq[300];
int p;
stack<int> stk;
LL calc(LL a, LL b, char c)
{
switch(c)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
case '/':
return a/b;
}
}
LL solve()
{
int e = p--;
if(eq[e].c == '\0')
return eq[e].n;
else
{
LL b = solve();
LL a = solve();
return calc(a, b, eq[e].c);
}
}
int main()
{
char s[260];
LL num = 0;
cin.getline(s, 260);
for(int i = 0; s[i] != '@'; ++i)
{
if(s[i] >= '0' && s[i] <= '9')
num = num * 10 + (s[i] - '0');
else if(s[i] == ' ')
{
eq[++p].n = num;
num = 0;
}
else
eq[++p].c = s[i];
}
cout << solve();
return 0;
}
|