中缀表达式转换成后缀表达式

中缀表达式即普通的运算式子,运算符是以中缀形式处于操作数的中间(例:3 + 4),后缀表达式就是逆波兰式(例:3 4 +),中缀表达式转后缀表达式也是学习数据结构中的栈的时候一个典型的例子,结合上一次写到逆波兰式。可以用这种原理即输入普通式子(即中缀表达式),转换成后缀表达式,然后通过后缀表达式(逆波兰式)的计算,可以得出结果。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #define STACK_INIT_SIZE 20
  4 #define STACK_INCREMENT 10
  5 typedef char ElemType;
  6 typedef char Status;
  7 
  8 typedef struct
  9 {
 10     ElemType *base;
 11     ElemType *top;
 12     int stacksize;
 13 }SqStack;
 14 
 15 Status InitStack( SqStack *S )
 16 {
 17     S->base = ( ElemType *) malloc (  STACK_INIT_SIZE*sizeof( ElemType ) );
 18     S->top  = S->base ;
 19     S->stacksize = STACK_INIT_SIZE;
 20 
 21     return 0;
 22 }
 23 
 24 //插入元素e,即入栈
 25 Status Push( SqStack *S , ElemType e )
 26 {
 27     if ( S->top - S->base >= S->stacksize )  //当前容量大于或等于最大容量
 28     {
 29     //追加栈的空间
 30     S->base = ( ElemType *) realloc ( S->base,  S->stacksize + STACK_INCREMENT*sizeof( ElemType ) );
 31     if ( !S->base )
 32         return  -1;
 33     S->top = S->base  + S->stacksize ;
 34     S->stacksize = S->stacksize + STACK_INCREMENT;
 35 
 36     }
 37     //开始赋值
 38     *S->top = e;
 39     S->top++;
 40 
 41     return 0;                              //注意返回值为0,不是e
 42 }
 43 
 44 //弹出元素e,即出栈
 45 Status Pop ( SqStack *S , ElemType *e )//此处S为结构体指针的变量,所以访问结构体成员用"->"
 46 {
 47     //首先判断栈内是否为空
 48     if ( S->top == S->base )
 49     return -1 ;
 50 
 51     --S->top ;
 52     *e = *S->top ;
 53 
 54     return *e;                         //注意返回值为e,不是0
 55 }
 56 
 57 int StackLen ( SqStack S )//S为结构体变量,所以访问结构体成员用"."
 58 {
 59     return  ( S.top - S.base );
 60 }
 61 
 62 int main()
 63 {
 64    SqStack s;
 65    char c,e;
 66    InitStack(&s);
 67    printf("请按中缀表达式输入式子,以'#'作为结束符:\n");
 68    scanf("%c",&c);
 69    while(c!='#')
 70    {
 71        while(c>='0'&&c<='9')
 72        {
 73            printf("%c",c);
 74            scanf("%c",&c);
 75            if(c<'0'||c>'9')
 76            {
 77                printf(" ");
 78            }
 79        }
 80            if(')'==c)
 81            {
 82                 Pop(&s,&e);
 83                 while('('!=e)
 84                 {
 85                     printf("%c ",e);
 86                     Pop(&s,&e);
 87                 }
 88            }
 89            else if('+'==c||'-'==c)
 90            {
 91                if(!StackLen(s))
 92                {
 93                    Push(&s,c);
 94                }
 95                else
 96                {
 97                    do
 98                    {
 99                        Pop(&s,&e);
100                        if('('==e)
101                        {
102                            Push(&s,e);
103                        }
104                        else
105                        {
106                            printf("%c ",e);
107                        }
108                    }while(StackLen(s)&&'('!=e);
109                    Push(&s,c);
110                }
111            }
112 
113            else if('*'==c||'/'==c||'('==c)
114            {
115                 Push(&s,c);
116            }
117            else if('#'==c)
118            {
119                break;
120            }
121            else
122            {
123                printf("\n 出错");
124                return -1;
125            }
126            scanf("%c",&c);
127    }
128        while(StackLen(s))
129        {
130            Pop(&s,&e);
131            printf("%c ",e);
132        }
133    return 0;
134 }

上面程序中几个注意点:一是出现iif(')'==c)的表达式,将')'写在了'=='的左边,这有助于调试发现错误,防止有些程序员将'=='打成'=';不然的话即使打成c=')'编译器也不会发现错误,认为是赋值,而')'=c这样的式子式错误的,因为无法将变量赋值给常数;二是入栈函数(Push)和出栈函数(Pop)作为子函数式写有关栈的程序的必备子程序,可以将他们制作成头文件,以后可以直接调用。三是编程的格式,因为while().if(),

else if()这样的语句太多,还有"{}"也很多,格式整齐了就不易出错并且便于调试发现错误。

运算结果中有空格,这也是需要在程序中改进的。

 

posted @ 2015-10-22 20:07  近水樓台  阅读(435)  评论(0编辑  收藏  举报
Fork me on GitHub
回到顶部