一、后缀表达式—栈的应用
1、理论
学习了栈,就有了一道完全使用栈来解决的实际的计算机问题:
后缀表达式
小学在数学运算的时候,都知道,先乘除、后加减,有括号的先计算括号里面的。比如 9+(3-1)× 3 +10 ÷2
很简单的一道题目,小学生都会。
可是,计算机不会。
我们并不能告诉计算机,先看看括号,然后又回过头去把括号里的内容运算一遍。那样太麻烦。
于是乎,有科学家就设计出了一套方便我们编程的法则—后缀表达式。
说了这么多,先来看看就知道了。
9+(3-1)× 3 +10 ÷2 这种把运算符放在式子中间的,叫做中缀表达式。
后缀表达式,顾名思义,就是运算符放在运算数字的后边。
变成了:9 3 1 - 3 × + 10 2 ÷ +
然后怎么利用栈操作的呢?如上所示,建立一个栈和一个指向当前栈的指针,把数字一个个 压入栈中,压入一个指针跟着加一,遇到运算符就取出当前指针指向的值和前一个值进行运算。把结果重新入栈。
如上图所示,这就是一次完整的运算。接下来就是不断重复以上的过程即可
2、做题
一般来说,后缀表达式的题目算法本身都不难实现。难的是每次题目所给出来的区分不同数字的方法不同。
比如洛谷的题目是“2 .3.10.”这是用实心点来代表
而VJ上这道题的就是纯空格来区分。
这道题只给出一行样例,就直接用一个字符串数组存储,然后指针沿着整个字符串一个个走即可,遇到一个空格(对应的ASCII码为32)就清算之前的数字。并且放入栈中。
#include <stdio.h>
#include <string.h>
#include<algorithm>
#include <math.h>
using namespace std;
char temp[20000];//用来放当前浮点数的
int t=0;//临时存放的指针
int main()
{
char s[200000];
gets(s);
double numStack[100000];//栈
int top=1;//栈顶指针
int cnt=0;
while(cnt<strlen(s))
{
if(s[cnt]==32)//是空格
{
t=0;
if(temp[0]!=0)
{
numStack[top]=atof(temp);//转换好,放入栈
}
else
{
cnt++;//跳过空格
continue;
}
top++;//栈顶指针移动
memset(temp,0,20000);//置空字符串数组,等待下次使用
cnt++;//跳过空格
continue;
}
if(s[cnt]<='9'&&s[cnt]>='0')//属于数字
{
temp[t]=s[cnt];
t++;
cnt++;
}else if(s[cnt]=='+'){
top--;
double a= numStack[top];
top--;
double b= numStack[top];
numStack[top] = b + a;
top++;//top必须永远指着空的那个
numStack[top] = 0 ;
cnt++;
}else if(s[cnt]=='-'){
top--;
double a= numStack[top];
top--;
double b= numStack[top];
numStack[top] = b - a;
top++;//top必须永远指着空的那个
numStack[top] = 0 ;
cnt++;
}else if(s[cnt]=='*'){
top--;
double a= numStack[top];
top--;
double b= numStack[top];
numStack[top] = b * a;
top++;//top必须永远指着空的那个
numStack[top] = 0 ;
cnt++;
}else if(s[cnt]=='/'){
top--;
double a= numStack[top];
top--;
double b= numStack[top];
numStack[top] = b / a;
top++;//top必须永远指着空的那个
numStack[top] = 0 ;
cnt++;
}else if(s[cnt]=='.'){
temp[t]=s[cnt];
t++;
cnt++;
}
}
printf("%.6lf\n",numStack[--top]);
return 0;
}
这是考核时候写的代码,虽然臃肿且过不了样例,总是WA, 但是找了好多例子都是正确,就先放着吧,毕竟对于后缀表达式算是运用正确