栈和队列的应用——逆波兰式

题目:编写算法,利用栈计算算术表达式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;
}

posted @ 2024-04-25 17:00  ulyee  阅读(26)  评论(0)    收藏  举报