题解 P1175 【表达式的转换】
Fuyang_KBZ · · 题解
蒟蒻没想到随便交了下就过了orz,使用的方法应该是最单纯的
分为两步:1.转后缀表达式存到last数组里
2.一边计算一边输出过程,我想到了一个比较好的方法
1:转后缀表达式,过程如下(数组均指last数组)
①遇到一个数直接存进数组
②遇到左括号,把他放进栈里
③遇到右括号,不断取出栈顶存进数组里
④遇到运算符,只要栈顶的运算符优先级大于等于当前读入的符号,就不断取出栈顶符号存入数组,最后把读入的符号进栈。优先级:乘方 > 乘除 > 加减 > 左括号。(右括号不会进栈)优先级定义详情看代码。
⑤依次把栈里的元素转存到数组里
2:计算过程并输出,使用一个数组模拟的栈,方便我们遍历,Top变量代表栈顶,start变量代表在last数组里的一个光标,因为我们采用的输出方式为:将栈中Top之前的变量输出,再将lst数组中start光标之后的所有元素输出就可以将一个过程完整的表达式,不理解的话可以看一下代码的具体操作体会一下
①遇到一个数,存进栈里,并将start后移一位
②遇到运算符,从栈顶连续取出两个元素进行运算,答案继续压栈(此时Top指针之前加上str指针之后的就是一个完整的式子)
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
#define ll long long
using namespace std;
int tot;
char a[1100],lst[1100];
int lev[300];
stack<char> s;
stack<int> Pro;
int len;
void E_change();
void cal();
void add(char);
int cf(int,int);
int main()
{
lev['^'] = 7,lev['*'] = 6,lev['/'] = 6,lev['+'] = 5,lev['-'] = 5,lev['('] = 4;//优先级定义,简单粗暴
scanf("%s",a);
len = strlen(a);
E_change();
int l = strlen(lst);
for(int i = 0; i < l; ++i) printf("%c ",lst[i]); //输出后缀表达式
printf("\n");
cal(); //计算
return 0;
}
void E_change() //转换后缀表达式
{
char c;
for(int i = 0; i <= len - 1; ++i){
c = a[i];
if(c >= '0' && c <= '9'){add(c);continue;}
if(c == '(') {s.push(c);continue;}
if(c == ')') {
while(s.top() != '('){
add(s.top());
s.pop();
}
s.pop();
continue;
}
if( (c == '+' || c == '-' || c == '*' || c == '/' || c == '^' )){
if(s.empty()) {s.push(c);continue;}
while(!s.empty()){
char ch = s.top();
if(lev[ch] < lev[c]) break;
if(lev[ch] >= lev[c]){
add(ch);
s.pop();
}
}
s.push(c);
}
}
while(!s.empty()){
add(s.top());
s.pop();
}
}
void cal()
{
int Pro[10001];
int Top = 0,str = 0;
int l = strlen(lst);
for(int i = 0 ; i < l; ++i){
char c = lst[i];
if(c >= '0' && c <= '9') {Pro[Top] = c - 48;Top++;str++;}
else{
int a = Pro[--Top];
int b = Pro[--Top];
str++;
int ans;
if(c == '+') ans = a + b;
else if(c == '-') ans = b - a;
else if(c == '*') ans = a * b;
else if(c == '/') ans = b / a;
else if(c == '^') ans = cf(b,a);
Pro[Top] = ans;
for(int j = 0; j <= Top; ++j) printf("%d ",Pro[j]);//栈中有一半式子
for(int j = str; j < l; ++j) printf("%c ",lst[j]);//str后面的都是未进栈的数
//两部分相拼就是完整的一个表达式
Top++;
printf("\n");
}
}
}
int cf(int x,int y)
{ //乘方运算
ll sum = 1;
for(int i = 1; i <= y; i++) sum = sum * x;
return sum;
}
void add(char x)
{
lst[tot++] = x;
// lst[++tot] = ' ';
}