DSAA之中缀转后缀表达式(三)

1. 简单回顾

  笔者认为该算法,只需要记住流程,而记住流程的关键就是多做几个笔试选择题,比如
牛客网

这里写图片描述

  可以完全按照中缀表达式转换成后缀表达式的算法来:

步骤 后缀表达式
遇到X输出 X
遇到=入栈 = X
遇到A输出 = XA
遇到A输出 = XA
遇到+,比=优先级高,入栈 =+ XA
遇到B输出 =+ XAB
遇到*,比+优先级高,入栈 =+* XAB
遇到(,直接入栈 =+*( XAB
遇到C输出 =+*( XABC
遇到-,栈顶是(,入栈 =+*(- XABC
遇到D输出 =+*(- XABCD
遇到),将栈直到(的运算符全部抛出,并丢弃() =+* XABCD-
遇到/,栈顶是,直接抛出,接着遇到+,优先级比/低,入栈/ =+/ XABCD-*
遇到E输出 =+/ XABCD-*E
遇到NULL,抛出全部栈中元素 XABCD-*E/+=

2. 算法实现

#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <string.h>
#include <ctype.h>
#define MAXSTACKSIZE 20
#define MAXSIZE  50
#define  handle_error(msg) do{ perror(msg); exit(-1);}while(0);
typedef   char TYPE;

typedef struct stack{
   int stacksize;
   int topofstack;
   TYPE  * arrary;
} STACK;

void destroy_stack();
TYPE pop();
TYPE top();
int push(TYPE );
STACK * creat_stack(int );
char * transfer_expression(char * );
int handle_experession(char *, char * );
STACK * ptr;


int main(void){
   char infixexpression[MAXSIZE];
   char * result;
   ptr=creat_stack(MAXSTACKSIZE);

   //获取表达式
   if(fgets(infixexpression,MAXSIZE,stdin) == NULL)
      errx(1, "gets error\n");
   result=transfer_expression(infixexpression);

   free(result);
   destroy_stack(ptr);
}


char * transfer_expression(char * infixexpression){
  char * ptr;
  if((ptr=calloc(strlen(infixexpression), sizeof(char))) == NULL)
     handle_error("malloc");
  handle_experession(infixexpression,ptr);
  printf("%s\n",ptr);
  return ptr;
}

int handle_experession(char * infixexpression, char * result){
    if(*infixexpression == '\n'||*infixexpression == '\0'){
       for(;top() != -1;){
            //debug
            //printf("out %c\n",top());
            *result++=pop();
       }
       return 0;
    }
    else if(isalnum(*infixexpression) != 0)
       *result++=*infixexpression;
    else
       switch(*infixexpression){
          case '*':
          case '/':
              for(;top() != -1;)
                  if(top() != '*' && top() != '/' || top() == '('){
                      push(*infixexpression);
                      //debug
                      //printf("in %c\n",top());
                      goto exit1;
                  }
                  else{
                      //debug
                      //printf("out %c\n",top());
                      *result++=pop();
                  }
              push(*infixexpression);
              //debug
              //printf("in %c\n",top());
              exit1: 
                  break;
          case '+':
          case '-':
              for(;top() != -1;)
                  if(top() == '('|| top() == '='){
                      push(*infixexpression);
                      //debug
                      //printf("in %c\n",top());
                      goto exit2;
                  }
                  else{
                      //printf("out %c\n",top());
                      *result++=pop();
                  }
              push(*infixexpression);
              //debug
              //printf("in %c\n",top());
              exit2:
                  break;
          case '(':
              push(*infixexpression);
              //debug
              //printf("in %c\n",top());
              break;
          case ')':
              do{
                 printf("out %c\n",top());
                 *result++=pop();
              }while(top() != '(');
              //debug
              //printf("pop %c\n",top());
              pop();
              break;
          case '=':
              for(;top() != -1;){
                  //debug
                  //printf("out %c\n",top());
                  *result++=pop();
              }
              push(*infixexpression);
              //debug
              //printf("in %c\n",top());
              break;
       }
       return handle_experession(infixexpression+1,result);
}



STACK * creat_stack(int stacksize){
   STACK * ptr;
   if((ptr=malloc(sizeof(STACK))) == NULL)
      handle_error("malloc");
   ptr->stacksize=stacksize;
   ptr->topofstack=-1;
   if((ptr->arrary=malloc(stacksize*sizeof(TYPE))) == NULL)
      handle_error("malloc");
   return ptr;
}

int push(TYPE value){
   if(ptr->topofstack== ptr->stacksize)
      return -1;
   (ptr->arrary)[++ptr->topofstack]=value;
   return 0;
}


TYPE pop(){
   if(ptr->topofstack== -1)
      return -1;
   return (ptr->arrary)[ptr->topofstack--];
}

TYPE top(){
   if(ptr->topofstack== -1)
      return -1;
   return (ptr->arrary)[ptr->topofstack];
}


void destroy_stack(){
   if(ptr != NULL){
      free(ptr->arrary);
      free(ptr);
   }
}

  结果:

[root@localhost ~]# ./3_3
x=a+b*(c-d)/e       #这里是输入的中缀表达式
xabcd-*e/+=
[root@localhost ~]# ./3_3
4*5+3*(6*9)/5       #这里是输入的中缀表达式
45*369**5/+
[root@localhost ~]# 

3. 回顾

  笔者对 handle_experession的实现,使用了递归的方式。最大的感触就是debug的重要性,我们不能保证一次输入的代码就百分百能运行,总是因为一些小细节错误,导致结果与预期不同。所以必须强制自己编程时就考虑debug点的设置。

猜你喜欢

转载自blog.csdn.net/LoveStackover/article/details/80039788