逆波兰
16:00~22:00花了好久好久学了一下这个东西
逆波兰真的好强
//逆波兰后缀表达式 利用堆栈实现 堆栈用数组实现
#include<bits/stdc++.h>
using namespace std;
#define stack astack
char stack[500];//存符号
char out[500],in[500];//输出 输入
int dtop,top,len;
double dstack[500];//存数字
int f1(int x)//阶乘
{
if(x==0||x==1)return 1;
else return x*f1(x-1);
}
bool isoperator(char ch)
{
return (ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='^'||ch=='!');
}
int prior(char a){
if(a=='+'||a=='-')return 1;
if(a=='*'||a=='/')return 2;
if(a=='^'||a=='!')return 3;
}//优先级赋值
void rePolish(char* a)
{
for(int i=0;i<strlen(a);i++)
{
if(isdigit(a[i]))
{
out[len++]=a[i];
while(isdigit(a[i+1])&&i<strlen(a)-1){
out[len++]=a[++i];
}//是数 就输出 输出不用printf而是存到out数组里
out[len++]=' ';
}
if(a[i]=='('){
stack[++top]=a[i];//左括号入栈 top要和指的地方一致
}
if(a[i]==')'){
while(stack[top]!='(')
out[len++]=stack[top--];
top--;
out[len++]=' ';
}//右括号不入栈 一直输出直到遇到左括号 栈顶top再减一下跳过左括号
while(isoperator(a[i])) //遇到操作符 如果优先级比栈顶的低 要把前面的优先级也高的全部弹出 因此必须用while
//if(isoperator(a[i])) 用if的话只能弹一下 如果是1*2*3+5 就只得到一个*号
{
if(prior(a[i])>prior(stack[top])||top==0||stack[top]=='(')
{
stack[++top]=a[i];//栈空或者优先级高就入栈 当前栈顶是左括号也要入栈
break;//需要break掉 while下一轮循环
}
else{
out[len++]=stack[top--];//优先级低就出栈 有括号也是这个效果
out[len++]=' ';
}
}
}
while(top)
{
out[len++]=stack[top--];
out[len++]=' ';
}//弹出栈里剩余的东西
}
double cal(double x,double y,char ch)
{
if(ch=='+')return x+y;
if(ch=='-')return x-y;
if(ch=='*')return x*y;
if(ch=='/')return x/y;
if(ch=='^')return pow(x,y);
}
double calculate(char *a)
{
char d[100];//定义一个字符数组 存数
for(int i=0;a[i];i++)
{
if(a[i]!=' '){
sscanf(a+i,"%s",d);//妙啊 利用前面打出的空格区分数 用sscanf读入一串数或者操作符到d里面
if(isdigit(d[0]))
dstack[++dtop]=atof(d);//超有用的函数atof 将字符转化成double char类型的123.456变成了double型的123.456000
else{
if(d[0]=='!'){
dstack[dtop]=(double)f1((int)dstack[dtop]);//单目 对栈顶操作就行
}
else{
dstack[dtop-1]=cal(dstack[dtop-1],dstack[dtop],d[0]);//双目运算的话 计算栈顶的两个数
dtop--;
}
}
}
while(a[i]&&a[i]!=' ')i++;
}
return dstack[dtop];
}
int main()
{
scanf("%s",in);
rePolish(in);
printf("%s\n",out);
printf("%lf\n",calculate(out));
return 0;
}