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点的设置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值