堆栈应用(后序表达式)

堆栈应用之后序表达式

  要求设计一个程序,能读取一个合法的中序表达式,将其转化为后序表达式并计算求值,输入的表达式可包括“+”“-”“*”“/”、正整数与圆括号,以“ # ”表示一个数字结束。

  这里,我们可以考虑堆栈思想来实现整个操作过程。

  首先,我们使用两个堆栈分别来储存结果与操作符,用一个字符串来储存中序表达式。至于有何作用我们待会儿再说。

 

#include<iostream>
#include<cstdlib>
#define maxn 10001
using namespace std;

char exp[maxn];//储存转换后的后序表达式
char stack[maxn];//作为栈使用
char str[maxn];//储存输入的中序表达式

 

  紧接着,让我们来思考一个中序表达式的转换过程。

  依次对字符串str进行扫描:

  1.若所得字符为数字则直接存入exp

  2.若所得字符为左括号则直接入栈;

  3.若所得字符为右括号,则将栈中位于对应的左括号之上的操作符全部存入exp并出栈,然后将该左括号删除;

  4.若所得字符为“+”“-”,则将栈顶端连续的“*”或“/”操作符全部存入exp并出栈然后将该操作符存入栈中(因为优先级最低);

  5.若所得字符为“*”“/”,则将栈顶端连续的“*”或“/”全部存入exp并出栈再将该操作符存入栈;

  6.若所得字符为“ # ”,则将当前栈中的所有运算符存入exp并出栈。

  这里我们举出表达式a+(b*c*e+d+f)的转化过程:

  1.a直接存入exp;

  2.“+”入栈;

  3.“( ”入栈;

  4.b直接存入exp

  5.“*”入栈;

  6.c直接存入exp

  7.栈顶“*”存入exp,并把当前扫描到的“*”存入栈中;

  8.将eexp中;

  9.将栈顶“*”存入exp,并把当前扫描到的“+”存入栈中;

  10.将d直接存入exp中;

  11.将“+”存入栈中;

  12.将f存入exp

  13.将栈中左括号之上的所有操作符存入exp

  14.将栈中剩余操作全部存入exp,转化完毕!

  最后,我们得到的结果为abc*e*df+++ .

  至于后序表达式的计算,我们详见代码。

 后序表达式(堆栈实现)代码如下:

 

//求表达式值
#include <cstdio>
#include<cstdlib>
#define MAX 100
char exp[MAX];   /*存储转换成的后缀表达式*/
#
void trans()     /*将算术表达式转换成后缀表达式*/
{
  char str[MAX];   /*存储原算术表达式*/
  char stack[MAX]; /*作为栈使用*/
  char ch;
  int sum,i,j,t,top=0;
  /*t作为exp的下标,top作为stack的下标,i作为str的下标*/
  printf("***************************************************************\n");
  printf("* 输入一个求值的表达式,以#结束。只能包含+,-,*,/运算符和正整数 *\n");
  printf("***************************************************************\n");
  printf("算术表达式:");
  i=0;   /*获取用户输入的表达式*/
  do
  {
     i++;
     scanf("%c",&str[i]);
  } while (str[i]!='#' && i!=MAX);
  sum=i; /*记录输入表达式总的字符个数*/
  t=1;i=1;
  ch=str[i];i++;
  while (ch!='#')
  {
    switch(ch)
    {
      case '(':  /*判定为左括号*/
           top++;stack[top]=ch;
           break;
      case ')':  /*判定为右括号*/
           while (stack[top]!='(')
           {
             exp[t]=stack[top];top--;t++;
           }
           top--;
           break;
      case '+':   /*判定为加减号*/
      case '-':
            while (top!=0 && stack[top]!='(')
            {
              exp[t]=stack[top];top--;t++;
            }
            top++;stack[top]=ch;
            break;
       case '*':  /*判定为'*'或'/'号*/
       case '/':
            while (stack[top]=='*' || stack[top]=='/')
            {
                     exp[t]=stack[top];top--;t++;
            }
            top++;stack[top]=ch;
            break;
       case ' ':break;
       default:
            while (ch>='0' && ch<='9') /*判定为数字*/
            {
               exp[t]=ch;t++;
               ch=str[i];i++;
            }
            i--;
            exp[t]='#';t++;
     }
     ch=str[i];i++;
  }
  while (top!=0)
  {
    exp[t]=stack[top];t++;top--;
  }
  exp[t]='#';
  printf("\n\t原来表达式:");
  for (j=1;j<sum;j++) printf("%c",str[j]);
    printf("\n\t后缀表达式:",exp);
  for (j=1;j<t;j++)
    printf("%c",exp[j]);
}
   
void compvalue()  /*计算后缀表达式的值*/
{
  float stack[MAX],d; /*作为栈使用*/
  char ch;
  int t=1,top=0;  /*t作为exp的下标,top作为stack的下标*/
  ch=exp[t];t++;
  while (ch!='#')
  {
    switch (ch)
    {
       case '+':stack[top-1]=stack[top-1]+stack[top];
            top--;break;
       case '-':stack[top-1]=stack[top-1]-stack[top];
            top--;break;
       case '*':stack[top-1]=stack[top-1]*stack[top];
            top--;break;
       case '/':if (stack[top]!=0)
                   stack[top-1]=stack[top-1]/stack[top];
                else
                {
                   printf("\n\t除零错误!\n");
                   exit(0);/*异常退出*/
                }
                top--;break;
       default:d=0;
               while (ch>='0' && ch<='9')   /*判定为数字字符*/
                {
                  d=10*d+ch-'0';  /*将数字字符转换成对应的数值*/
                  ch=exp[t];t++;
                }
                top++;
                stack[top]=d;
    }
    ch=exp[t];t++;
  }
  printf("\n\t计算结果:%g\n",stack[top]);
}

int main()
{
  trans();
  compvalue();
  system("pause");
}

  以上就是代码实现了!

  若有不足,请指正!

posted @ 2018-12-11 18:13  宫锁匠心  阅读(569)  评论(0)    收藏  举报