本实验取材于浙江大学《数据结构》,计算后缀表达式,关键在于理解堆栈的工作顺序
//堆栈的应用案例--表达式求值
//表达式求值的基本步数
//1当读入的是一个运算数时,把它被压入栈中;
//2当读入的是一个运算符时,就从堆栈中弹出适当数量的运算数
//对该运算进行计算,计算结果再压回到栈中。
//处理完整个后缀表达时之后,堆栈顶上的元素就是表达时的结果值
下面利用堆栈的顺序存储进行运算!
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXOP 100//操作数序列可能的最大长度
#define INFINITY 1e9//代表正无穷
#define ERROR -1
typedef double ElementType;//将堆栈的元素类型具体化
//类型依次对应运算符、运算符、字符串结尾
typedef enum{num,opr,end} Type;
typedef int Position;
typedef struct SNode *PtrToStack;
struct SNode{
ElementType *Data;
Position Top;
int MaxSize;
};
typedef PtrToStack Stack;
Stack CreateStack(int MaxSize);//生成空堆栈,其最大长度为Maxsize
int IsFull(Stack S);//判断堆栈S是否已满
int Push(Stack S,ElementType X);//将元素item压入堆栈
int IsEmpty(Stack S);//判断堆栈S是否为空
ElementType Pop(Stack S);//删除并返回栈顶元素
Stack CreateStack(int MaxSize){
Stack S=(Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType *)malloc(MaxSize*sizeof(ElementType));
S->Top = -1;
S->MaxSize = MaxSize;
return S;
}
int IsFull(Stack S){
return (S->Top==S->MaxSize-1);
}
int Push(Stack PtrS,ElementType X)
{
if(IsFull(PtrS)){
printf("堆栈满");
return ERROR;
}else{
PtrS->Data[++(PtrS->Top)] = X;
return PtrS->Data[PtrS->Top];
}
}
int IsEmpty(Stack S){
return (S->Top==-1);
}
ElementType Pop(Stack PtrS)
{
if(PtrS->Top==-1){
printf("堆栈空");
return ERROR;
}else{
return (PtrS->Data[(PtrS->Top)--]);
}
}
Type Getop(char *Expr,int *start,char *str)
{
//从*start开始读入下一个对象(操作数或运算符),并
//保存在字符串str中
int i=0;
while((str[0]=Expr[(*start)++])==' ');
while(str[i]!=' ' && str[i]!='\0')
str[++i]=Expr[(*start)++];
if(str[i]!='\0')//如果读到输入结尾
(*start)--;//start指向结束符
str[i]='\0';//结束一个对象的获取
if(i==0) return end;//读到了结束
else if(isdigit(str[0]) || isdigit(str[1]))
return num;//表示此时str中存的是一个数字
else //表示str不是空串,又不是数字
return opr; //表示此时str中存的是一个运算符
}
ElementType PostfixExp(char *Expr)
{
Stack S;
Type T;
ElementType Op1,Op2;
char str[MAXOP];
int start=0;
//申请一个新堆栈
S=CreateStack(MAXOP);
Op1 = Op2=0;
while((T=Getop(Expr,&start,str))!= end){
//当为读到输入结束时
if(T==num)
Push(S,atof(str));
else{
if(!IsEmpty(S)) Op2 = Pop(S);
else Op2 = INFINITY;
if(!IsEmpty(S)) Op1 = Pop(S);
else Op2 = INFINITY;
switch(str[0]){
case '+':Push(S,Op1+Op2);break;
case '*':Push(S,Op1*Op2);break;
case '-':Push(S,Op1-Op2);break;
case '/':
if(Op2 != 0.0)
Push(S,Op1/Op2);
else{
printf("falut div is zero\n");
Op2 = INFINITY;
}
break;
default:
printf("fault unknown fault%s\n",str);
Op2 = INFINITY;
break;
}
if(Op2>=INFINITY) break;
}
}
if(Op2<INFINITY)
if(!IsEmpty(S))
Op2=Pop(S);
else
Op2 = INFINITY;
free(S);
return Op2;
}
int main()
{
char Expr[MAXOP];
ElementType f;
gets(Expr);
f=PostfixExp(Expr);
if(f<INFINITY)
printf("%.4f\n",f);
else
printf("function is fault\n");
return 0;
}