栈和队列的应用——逆波兰式
题目:编写算法,利用栈计算算术表达式4+2*3-9/5 的值。
要求:利用栈的基本操作来实现。
算法逻辑:
①首先,定义一个存放字符型数据的栈S,存放运算符,用于将中缀表达式转化为后缀表达式;定义一个存放算术表达式的数组s[MaxSize]={'4','+','2','*','3','-','9','/','5'};再定义一个存放算术表达式的数组st[MaxSize],用于存放转化后的后缀表达式。
②定义一个转化函数transform(s,st,&S),用于将中缀表达式转化为后缀表达式。
③设置循环,输出后缀表达式。
④定义一个运算函数mathematic(double a,char c,double b),用于对后缀表达式进行四则运算。
⑤定义一个存放浮点型数据的栈DS,用于存放运算结果。
⑥定义一个运算函数calculate(st,&DS),用于计算后缀表达式st[MaxSize]。
⑦运算结果存在栈DS中,将栈DS中的最后一个数出栈,输出,保留两位小数。
源代码:
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
typedef char ElemType; //假设顺序栈中所有元素为char类型
typedef struct
{ ElemType data[MaxSize]; //存放栈中的元素
int top; //栈顶指针
} Stack;
void InitStack(Stack *S)
//由于L要回传给实参,所以用引用类型
{
S->top=-1;
}
int Push(Stack *S,ElemType x)
{
int k;
if(S->top+1==MaxSize)
{
printf("overflow error!\n");
return 0;
}
S->top++;
S->data[S->top]=x; //
return 1;
}
int Pop(Stack *S,ElemType *x)
{
if(S->top==-1)
return 0;
*x=S->data[S->top];
S->top--;
return 1;
}
int StackEmpty(Stack *S)
{
if(S->top==-1)
return 1;
else
return 0;
}
int GetTop(Stack *S,ElemType *e)
{
if(StackEmpty(S))
return 0;
*e=S->data[S->top];
return 1;
}
//创建一个存放字符型数据的栈
typedef struct
{ double data[MaxSize]; //存放栈中的元素
int top; //栈顶指针
} DStack;
void DInitStack(DStack *DS)
//由于L要回传给实参,所以用引用类型
{
DS->top=-1;
}
int DPush(DStack *DS,double x)
{
int k;
if(DS->top+1==MaxSize)
{
printf("overflow error!\n");
return 0;
}
DS->top++;
DS->data[DS->top]=x; //
return 1;
}
int DPop(DStack *DS,double *x)
{
if(DS->top==-1)
return 0;
*x=DS->data[DS->top];
DS->top--;
return 1;
}
int DStackEmpty(DStack *DS)
{
if(DS->top==-1)
return 1;
else
return 0;
}
//将中缀表达式s,通过栈S,转化为后缀表达式st
void transform(char s[],char st[],Stack* S){
//i是存放中缀表达式s数组的下标,j存放后缀表达式st数组的下标
int i=0,j=0;
char ch; //用于接收出栈的字符
while (s[i]!='\0'){
if (s[i]>='0' && s[i]<='9'){ //数字直接存进去
st[j]=s[i];
j++;
}
else if (s[i]=='+' || s[i]=='-'){
//栈非空并且栈顶不为左括号,将之前的运算符都存进去
while (!StackEmpty(S) && S->data[S->top]!='(' ){
Pop(S,&ch); //将上一个运算符出栈
st[j]=ch; //存进st数组
j++;
}
Push(S,s[i]); //将当前运算符进栈
}
else if (s[i]=='*' || s[i]=='/' || s[i]=='('){
//栈非空,栈顶不为左括号,并且栈顶为乘号或除号,将前一个运算符存进去
if (S->top!=-1 && S->data[S->top]!='(' &&
(S->data[S->top]=='*' || S->data[S->top]=='/') )
{
Pop(S,&ch); //将上一个运算符出栈
st[j]=ch; //存进st数组
j++;
}
Push(S,s[i]); //将当前运算符进栈
}
else if (s[i]==')'){
//将之前的运算符存进去,直到遇见左括号
while(S->data[S->top]!='('){
Pop(S,&ch); //将上一个运算符出栈
st[j]=ch; //存进st数组
j++;
}
S->top--; //丢弃左括号和右括号
}
i++; //移至下一个字符
}
//将剩下的符号出栈,存放在数组st中
while (!StackEmpty(S)){
Pop(S,&ch); //将上一个运算符出栈
st[j]=ch; //存进st数组
j++;
}
st[j]='\0'; //表示结束
}
//进行四则运算
double mathematic(double a,char c,double b){
if (c=='+'){
return a+b;
}
else if (c=='-'){
return a-b;
}
else if (c=='*'){
return a*b;
}
else if (c=='/'){
return a/b;
}
}
//对后缀表达式进行计算
void calculate(char st[],DStack* DS){
//将st中的字符一个个进行判断,DS存放要计算的数
int i=0;
char ch; //ch用于接受符号
double a,b,t,d;
while (st[i]!='\0'){
if (st[i]>='0' && st[i]<='9'){ //若是数字直接入栈
d=st[i]-'0'; //将数字字符转化成浮点数
DPush(DS,d); //入栈
}else { //若是符号进行计算
ch=st[i]; //ch存放运算符
DPop(DS,&b); //弹出两个数
DPop(DS,&a);
t=mathematic(a,ch,b); //调用mathematic函数进行计算
DPush(DS,t); //将计算结果入栈
}
i++; //移至下一个字符
}
}
int main(){
Stack S; //存放运算符,用于将中缀表达式转化为后缀表达式
InitStack(&S); //初始化
char s[MaxSize]={'4','+','2','*','3','-','9','/','5'}; //存放原中缀表达式
//char s[MaxSize];gets(s);
char st[MaxSize]; //存放转化后的表达式
transform(s,st,&S); //将中缀表达式转化为后缀表达式
int i=0;
while (st[i]!='\0'){ //输出后缀表达式
printf("%c,",st[i]);
i++;
}
DStack DS; //定义一个存放浮点型数据的栈
DInitStack(&DS); //初始化
calculate(st,&DS); //计算后缀表达式
double e; //e存放栈DS最后一个出栈的数据
DPop(&DS,&e); //将栈中的最后一个数出栈
printf("\n运算结果是:");
printf("\n%.2lf",e); //输出,保留两位小数
return 0;
}

浙公网安备 33010602011771号