称9+(3-1)*5+10/2这样的表达式为中缀表达式,称9 3 1 - 3 * + 10 2 / +这样的形式为后缀(逆波兰 RPN)表达式(数字在前运算符在后)。
一、将中缀表达式转为后缀表达式:
1、遍历中缀表达式中的数字和符号
①对于数字:直接输出(即直接成为后缀表达式的一部分);
②对于符号:
1`左括号:进栈;
2`符号:与栈顶符号进行优先级比较
· 栈顶符号优先级低则进栈;
· 栈顶符号优先级不低则将栈顶符号弹出并输出之后 再将此符号压入栈中;
3`右括号:将栈顶符号弹出并输出,知道匹配左括号(左括号也弹出);
2、遍历结束:
将栈中的所有符号弹出并输出。
算法框架:
transform(exp) { 创建栈S; i=0; while(exp[i] != '\0') { if(exp[i]为数字) { output(exp[i]); } else if(exp[i]为符号) { while(exp[i]优先级 <= 栈顶符号的优先级) { output(栈顶符号); pop(S); } push(S,exp[i]); } else if(exp[i]为左括号) { push(S,exp[i]); } else if(exp[i]为右括号) { while(栈顶符号不为左括号) { output(栈顶符号); pop(S); } 从S中弹出左括号; } else { 报错,停止循环; } i++; } while( (size(S) > 0) && (exp[i] == '\0') ) { output(栈顶符号); pop(S); } }
二、四则运算
1、遍历后缀表达式中的数字和符号
①对于数字:进栈;
②对于符号:
·从栈中弹出右操作数;
·从栈中弹出左操作数;
·根据符号进行运算;
·将结果压入栈中;
2、遍历结束:
栈中的唯一数字为计算结果。
算法框架:
compute(exp) { 创建栈S; i=0; while(exp[i] != '\0') { if(exp[i]为数字) { push(S, exp[i]); } elseif(exp[i]为符号) { 1从栈中弹出右操作数; 2从栈中弹出左操作数; 3根据符号进行运算; 4push(S, 结果); } else { 报错,停止循环; } i++; } if( (size(S) == 1) && (exp[i] == '\0') ) { 栈中唯一的数字为运算结果; } 返回结果; }
三、代码实现
#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include "Compute.h" #include "LinkStack.h" int Isnumber(char c) { return ('0' <= c ) && ( '9' >= c ); } int Isoperator(char c) { return ( '+' == c ) || ( '-' == c ) || ( '*' == c ) || ( '/' == c ); } int Priority(char c) { int ret = 0; if( ('+' == c) || ('-' == c) ) ret = 1; if( ('*'== c) || ('/'==c) ) ret =2; return ret; } int Isleftbracket(char c) { return ( '(' == c ); } int Isrightbracket(char c) { return ( ')' == c ); } char* Transform(const char* exp) { LinkStack* stack = LinkStack_Create(); int i = 0; char* ret = (char*)malloc(sizeof(char)); //动态申请字符串数组 int a = 0; //用于动态改变字符串数组大小 while( exp[i] != '\0' ) { if( Isnumber(exp[i]) ) { ret = (char*)realloc(ret,(a+1)*sizeof(char)); //可更改由malloc函数分配的内存空间大小 if( ret == NULL ) { printf("error"); break; } ret[a] = exp[i]; a++; } else if( Isoperator(exp[i]) ) { while( Priority(exp[i]) <= Priority((char)(long)LinkStack_Top(stack)) ) { ret = (char*)realloc(ret,(a+1)*sizeof(char)); if( ret == NULL ) { printf("error"); break; } ret[a] = (char)(long)LinkStack_Top(stack); a++; LinkStack_Pop(stack); } LinkStack_Push( stack, (void*)(long)exp[i] ); } else if( Isleftbracket(exp[i]) ) LinkStack_Push( stack, (void*)(long)exp[i] ); else if( Isrightbracket(exp[i]) ) { while( !Isleftbracket((char)(long)LinkStack_Top(stack)) ) { ret = (char*)realloc(ret,(a+1)*sizeof(char)); if( ret == NULL ) { printf("error"); break; } ret[a] = (char)(long)LinkStack_Top(stack); a++; LinkStack_Pop(stack); } LinkStack_Pop(stack); } else { printf("Invalid expression!!!"); break; } i++; } while( (LinkStack_Size(stack) > 0) && ( exp[i] == '\0' ) ) { ret = (char*)realloc(ret,(a+1)*sizeof(char)); if( ret == NULL ) { printf("error"); break; } ret[a] = (char)(long)LinkStack_Top(stack); a++; LinkStack_Pop(stack); } LinkStack_Destroy(stack); return ret; } long value(char c) { return (c-'0'); } long express(long left, long right, char exp) { long ret = 0; switch(exp) { case '+' : ret = left + right; break; case '-' : ret = left - right; break; case '*' : ret = left * right; break; case '/' : ret = left /right; break; } return ret; } long Compute(const char* exp) { LinkStack* stack = LinkStack_Create(); long ret = 0; int i = 0; while(exp[i] != '\0') { if( Isnumber(exp[i]) ) LinkStack_Push( stack, (void*)value(exp[i]) ); else if( Isoperator(exp[i]) ) { long right = (long)LinkStack_Pop(stack); long left = (long)LinkStack_Pop(stack); long result = express(left, right, exp[i]); LinkStack_Push(stack, (void*)result); } else { printf("Invalid expression!!!"); break; } i++; } if( (LinkStack_Size(stack) == 1) && (exp[i] == '\0') ) ret = (long)LinkStack_Pop(stack); else printf("Invalid expression"); LinkStack_Destroy(stack); return ret; }