题解 P1449 【后缀表达式】
Scarlet_Lightning · · 题解
此题是一道使用栈(stack)的裸题。。。
思路根P1981表达式求值非常像。
重点:此题由于采用后缀表达方式,所以在读到运算符号时可以无条件运算,无需考虑优先级,比P1981简单!!!(也就是说不用符号栈)
思路:先将整个表达式一起读入,接下来:
- 如果碰到数字,将其放入临时数组当中,方便以后求数字
- 如果碰到'.',那么将临时数组中的字符串转化成数字(具体操作看程序注释),将其压入数字栈中
- 如果碰到运算符号,那么将栈顶的两个元素取出做相应的运算(注意:如果碰到-'或'/'应该用栈顶第二个元素减或除以栈顶元素!!!)
- 最后输出数字栈中剩余的最后一个元素即可
模拟(想抄代码的童鞋们可以跳过此部分):
输入:3.18.56.+*@
碰到数字3,放入临时数组中:
stack ccty:3|*|*|*|*|*|*|
栈顶-> 空
栈底-> 空 read:3
接下来发现'.',转化数字压入数字栈中:
stack ccty:*|*|*|*|*|*|*|*
栈顶->
栈底-> 3 read:.
接下来碰到1,放入临时数组中:
stack ccty:1|*|*|*|*|*|*|*
栈顶->
栈底-> 3 read:1
接下来快速模拟:
stack ccty:1|8|*|*|*|*|*|*
栈顶-> 18
栈底-> 3 read:8
stack ccty:5|*|*|*|*|*|*|*
栈顶-> 18
栈底-> 3 read:5
stack ccty:5|6|*|*|*|*|*|*
栈顶-> 56
18
栈底-> 3 read:6
接下来读入加号。
将数字栈栈顶两个元素相加并将和压回数字栈中:
stack ccty:*|*|*|*|*|*|*|*
栈顶-> 74 18+56=74
栈底-> 3 read:+
同理:
stack ccty:*|*|*|*|*|*|*|*
栈顶-> 74*3=222
栈底-> 222 read:*
故最后答案等于222(好不吉利的数字)。
接下来请看代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<cstring>
#define is ==//装b
#define isnot !=
using namespace std;
stack<int>num;//数字栈
int Num;
char Ch;
int num2;
char str[10001];//表达式
char ccty[21];//临时数组
int flag=0,i;//flag用来判断数字是否已读尽
int numa,numb;
int Makenum(){//将临时数组中的字符转化成数字的函数
int ret=0;
for(int i=0;i<=strlen(ccty)-1;++i){
if(ccty[i]=='*')break;
ret=ret*10+ccty[i]-'0';
ccty[i]='*';//边转化边清空,省时间
}
return ret;//返回转化后的值
}
int main()
{
cin>>str;//读入整个表达式
char cha;//当前碰到的字符
cha=str[0];
int k=0;
while(cha!='@'){//如果未发现结束符号,那么运行
if(flag==0)i=0;
if(cha>='0'&&cha<='9'){//如果是数字
flag=1;
ccty[i]=cha;//将它塞入临时数组中
i++;
}
if(cha is '.'){//自己看上边的装b定义
flag=0;//数已读尽
Num=Makenum();//转化成数字
num.push(Num);//压入栈中
}
if((cha<'0'||cha>'9')&&cha isnot '.'){//装b*2
numa=num.top();
num.pop();
numb=num.top();
num.pop();//取出栈顶前两个数字
if(cha=='+')num.push(numb+numa);//加和乘反不反无所谓
if(cha=='-')num.push(numb-numa);//减和除就一定要反过来了
if(cha=='*')num.push(numb*numa);
if(cha=='/')num.push(numb/numa);
}
k++;
cha=str[k];//读取下一个字符
}
cout<<num.top();//输出答案
}
题外话:这里是栈(stack)的class类代码(不想用STL的童鞋们可以参考):
/*说明:stk.push(n)表面上是将n压入stk中,实际上是将n
压入stk中包含的a数组内*/
template<typename T>class stack{
T a[100001];
int tail;
public:
void push(T n){//压入数据
a[tail++]=n;
}
void pop(){//弹出栈顶元素
tail--;
}
T top(){//返回栈顶元素
return a[tail-1];
}
int size(){//返回栈内元素的个数
return tail;
}
bool empty(){//判断栈是否为空
return tail==0;
}
};
用法:
stack<元素基类型> 类名;
如:
stack<char> stk//建立一个存储字符的名为stk的栈
stack<int> num//建立一个存储int整型的名为num的栈
stack<double> dou//同上