表达式求值
波兰表示法(Polish notation,或波兰记法),是一种逻辑、算术和代数表示方法,其特点是操作符置于操作数的前面,因此也称做前缀表示法。如果操作符的元数(arity)是固定的,则语法上不需要括号仍然能被无歧义地解析。波兰记法是波兰数学家扬·武卡谢维奇1920年代引入的,用于简化命题逻辑。
“ 扬·武卡谢维奇本人提到:我在1924年突然有了一个无需括号的表达方法,我在文章第一次使用了这种表示法。 ”
—— Łukasiewicz(1), p. 610, footnote.
阿隆佐·邱奇在他的经典著作《数理逻辑》中提出该表达方法是一种值得被关注的记法系统,甚至将它与阿弗烈·诺夫·怀海德和伯特兰·罗素在《数学原理》中的逻辑表达式相提并论。
波兰表达式也叫后缀表达式
栈的定义及其基本操作
#include "stdafx.h"
#include "stdlib.h"
#include "string.h"
#define MaxSize 10
#define bool int
#define true 1
#define false 0;
typedef struct
{
int top;
int *data;
}SqStack;
typedef struct
{
int top;
char *data;
}SqStack_Oper;
bool IsEmpty(SqStack S)
{
if(S.top==-1)
return true;
else
return false;
}
bool IsFull(SqStack S)
{
if(S.top==MaxSize-1)
return true;
else
return false;
}
int GetTopElem(SqStack S)
{
if(IsEmpty(S))
return -1;
else
return S.data[S.top];
}
bool PushStack(SqStack *S,int e)
{
if(IsFull(*S))return false;
S->top++;
S->data[S->top]=e;
return true;
}
bool PopStack(SqStack *S,int *e)
{
if(IsEmpty(*S))return false;
*e=S->data[S->top];
S->top--;
return true;
}
bool IndexOf(char str[],char x)
{
long len=strlen(str);
for(int i=0;i<len;i++)
{
if(str[i]==x)
return true;
}
return false;
}
//主要用于计算括号的个数
int IndexOf_Blacket(char str[],char x)
{
int j=0;
long len=strlen(str);
for(int i=0;i<len;i++)
{
if(str[i]==x)
j++;
}
return j;
}
void InitStack(SqStack *S)
{
S->top=-1;
S->data=(int*)malloc(sizeof(int));
for(int i=0;i<MaxSize-1;i++)
{
S->data[i]=-1;
}
}
bool IsEmpty_Oper(SqStack_Oper S)
{
if(S.top==-1)
return true;
else
return false;
}
bool IsFull_Oper(SqStack_Oper S)
{
if(S.top==MaxSize-1)
return true;
else
return false;
}
char GetTopElem_Oper(SqStack_Oper S)
{
if(IsEmpty_Oper(S))
return NULL;
else
return S.data[S.top];
}
bool PushStack_Oper(SqStack_Oper *S,char e)
{
if(IsFull_Oper(*S))return false;
S->top++;
S->data[S->top]=e;
return true;
}
bool PopStack_Oper(SqStack_Oper *S,char *e)
{
if(IsEmpty_Oper(*S))return false;
*e=S->data[S->top];
S->top--;
return true;
}
void InitStack_Oper(SqStack_Oper *S)
{
S->top=-1;
S->data=(char*)malloc(sizeof(char));
for(int i=0;i<MaxSize-1;i++)
{
S->data[i]=' ';
}
}
int OperationCaculate(int left,int right,char opera)
{
int result=-1;
switch(opera)
{
case '+':result=left+right;break;
case '-':result=left-right;break;
case '*':result=left*right;break;
case '/':result=left/right;break;
}
return result;
}
bool CompareOpera(char og,char des)
{
if(des==NULL||og==NULL){
return false;
}
else if(IndexOf("+,-",des)&&IndexOf("+,-,*,/",og))
return true;
else if(IndexOf("+,-,*,/",des)&&IndexOf("*,/",og))
return true;
else
return false;
}
后缀表达式求值
int SuffixExpressionCaculate(char origin[])
{
int originlen=strlen(origin);
if(originlen<=0) return NULL;
int result;
SqStack S;
InitStack(&S);
for(int i=0;i<originlen;i++)
{
if(IndexOf("+,-,*,/",origin[i]))
{
int left_opera,right_opera;
if(PopStack(&S,&right_opera)&&PopStack(&S,&left_opera))
{
int result= OperationCaculate(left_opera,right_opera,origin[i]);
//printf("%d%c%d=%d\n",left_opera,origin[i],right_opera,result);
PushStack(&S,result);
}else
return NULL;
}
else
{
int og=origin[i]-'0';
PushStack(&S,og);
}
}
if(!IsEmpty(S))
result=GetTopElem(S);
return result;
}
中缀转换为后缀表达式
char* OrignalExpToSuffixExp(char origin[])
{
int originlen=strlen(origin);
if(originlen<=0) return NULL;
int blacket_count=IndexOf_Blacket(origin,'(');//获取括号个数
char *result=(char *)malloc(sizeof(char));
int j=0;
SqStack_Oper S;
InitStack_Oper(&S);
for(int i=0;i<originlen;i++)
{
if(blacket_count>0&&IndexOf("(,)",origin[i]))
{
if(origin[i]=='(')
{
PushStack_Oper(&S,origin[i]);
continue;
}
if(origin[i]==')')
{
blacket_count--;
int top=S.top;
char top_opera;
char des=GetTopElem_Oper(S);
while(des!='(')
{
if(PopStack_Oper(&S,&top_opera))
result[j++] =top_opera;
des=GetTopElem_Oper(S);
}
PopStack_Oper(&S,&top_opera);//把(退出栈
}
}
else if(IndexOf("+,-,*,/",origin[i]))
{
if(blacket_count==0)
{
int top=S.top;
bool flag=false;
while(!flag)
{
char des=GetTopElem_Oper(S);
if(S.top!=-1&&CompareOpera(des,origin[i]))
{
char top_opera;
if(PopStack_Oper(&S,&top_opera))
result[j++] =top_opera;
}
else
{
flag=true;
}
}
PushStack_Oper(&S,origin[i]);//把当前符号压栈
}
else
{
PushStack_Oper(&S,origin[i]);
}
}
else
{
result[j++]=origin[i];
}
}
while(!IsEmpty_Oper(S))//把剩余栈中的符号输出
{
char top_opera;
if(PopStack_Oper(&S,&top_opera))
result[j++] =top_opera;
}
return result;
}
测试代码
int main(int argc, char* argv[])
{
//测试后缀表达式计算
char suffix_expr[]="5311+-/3*211++-";
int result=SuffixExpressionCaculate(suffix_expr);
printf("测试后缀表达式计算:");
printf("SuffixExpressionCaculate(%s)=%d\n",suffix_expr,result);
//测试中缀表达式转换成后缀表达式
char origin_expr[]="((5/(3-(1+1)))*3)-(2+(1+1))";
char *result_ots=OrignalExpToSuffixExp(origin_expr);
printf("测试中缀表达式转换成后缀表达式:");
printf("OrignalExpToSuffixExp(%s)=%s\n",origin_expr,result_ots);
//测试中缀表达式转换成后缀表达式并计算
int result_otsc =SuffixExpressionCaculate(result_ots);
printf("测试中缀表达式转换成后缀表达式并计算:");
printf("SuffixExpressionCaculate(%s)=%d\n",origin_expr,result_otsc);
return 0;
}
测试结果
测试后缀表达式计算:SuffixExpressionCaculate(5311+-/3*211++-)=11
测试中缀表达式转换成后缀表达式:OrignalExpToSuffixExp(((5/(3-(1+1)))*3)-(2+(1+1)))=5311+-/3*211++-
测试中缀表达式转换成后缀表达式并计算:SuffixExpressionCaculate(((5/(3-(1+1)))*3)-(2+(1+1)))=11