重学数据结构:栈的应用-逆波兰表达式(C语言)

表达式求值

波兰表示法(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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值