前缀中缀后缀表达式

 

快要开始工作了,人生的第一份工作要格外重视,毕竟要有一个好的开始嘛。所以抽几天时间复习一下数据结构。看到堆栈部分,有一个运用堆栈的列子,表达式的中缀和前缀后缀的转换,刚开始找工作面试和笔试都遇到了这样的问题,以前模模糊糊的,现在搞明白了

一.表达式的三种形式:

中缀表达式:运算符放在两个运算对象中间,这是我们书写的时候最熟悉的一种形式,如:(2+1)*3

后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:2 1 + 3 *

前缀表达式:同后缀表达式一样,不包含括号,运算符放在两个运算对象的前面,如:* + 2 1 3

二.中缀表达式向后缀和前缀表达式的转换

转化的过程需要一个辅助的运算符堆栈op。并且要预先给运算符设置好运算的优先级如下所示:

struct

{

	char ch;

	int pri;

}

lpri[]={{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},

rpri[]={{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};

  我们可以看到同一个运算符作为左(对应lpri数组)、右(对应rlpri数组)运算符时他们的优先级不同,这是为了实现表达式求值时"从左到右计算"的规定设计的。为了方便算法的实现,在op堆栈的栈地存放的是'='作为终结。

将算术表达式exp转换成后缀表达式postexp的过程如下:

 

初始化运算符堆栈op;



将'='进栈;



从exp读取字符ch;



while(ch!='\0')

{

     if(ch不是运算符)

          将后续的所有数字均依次存放到postexp中,并以字符'#'标志数值串的结束;

   else

           switch(precede(op的栈顶运算符,ch))

           {

             case '<':     //栈顶运算符优先级低

               将ch进栈;

               从exp读取下一个字符ch;

               break;

         case '=':

                       退栈;

               从exp读取下一个字符ch;

               break;

         case '>':

                      退栈运算符并将其存放到postexp中;

               break;

         }

}



若字符串exp扫描完毕,则将运算符栈op中'='之前的所有运算符依次出栈并存放到

postexp中。最后得到后缀表达式postexp。

 

 具体的C语言代码如下:

#include "stdafx.h"

#include <iostream>



#define MaxOp 10

#define MaxSize 50



struct

{

	char ch;

	int pri;

}

lpri[]={{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},

rpri[]={{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};



int leftpri(char op)

{

	int i;

	for(i=0;i<MaxOp;i++)

		if(lpri[i].ch==op) return lpri[i].pri;

}



int rightpri(char op)

{

	int i;

	for(i=0;i<MaxOp;i++)

		if(rpri[i].ch==op) return rpri[i].pri;

}







int isOp(char ch)

{

	if(ch=='('||ch==')'||ch=='*'||ch=='/'||ch=='+'||ch=='-')

		return 1;

	else

		return 0;

}



int precede(char op1,char op2)

{

	if(leftpri(op1)==rightpri(op2))

		return 0;

	else

		if(leftpri(op1)<rightpri(op2))

			return -1;

		else

			return 1;

}



int precedeT(char op1,char op2)

{

	if(leftpri(op1)==rightpri(op2))

		return 0;

	else

		if(leftpri(op1)<rightpri(op2))

			return 1;

		else

			return -1;

}







void trans(char *exp,char postexp[])

{

	

	typedef struct

	{

		char data[MaxSize];

		int top;

	}OP;



	OP *op=(OP *)malloc(sizeof(OP));

	int i=0;

	op->top=-1;

	op->top++;

	op->data[op->top]='=';





	while(*exp!='\0')

	{

		if(!isOp(*exp))

		{

			while(*exp>='0'&&*exp<='9')

			{

				postexp[i++]=*exp;

				exp++;

			}

			postexp[i++]='#';

		}else

			switch(precede(op->data[op->top],*exp))

		{

			case -1:

				op->data[++op->top]=*exp;

				exp++;

				break;

			case 0:

				op->top--;

				exp++;

				break;

			case 1:

				postexp[i++]=op->data[op->top--];

				break;

		}

	}

	while(op->data[op->top]!='=')

	{

		postexp[i++]=op->data[op->top--];

	}

	postexp[i]='\0';

	

}



void transT(char *exp,char postexp[])

{

	

	typedef struct

	{

		char data[MaxSize];

		int top;

	}OP;



	OP *op=(OP *)malloc(sizeof(OP));

	int i=0;

	op->top=-1;

	op->top++;

	op->data[op->top]='=';

	int j=-1;

	char *p=exp;

	while(*p!='\0')

	{

		p++;

		j++;

	}



	while(j>-1)

	{

		if(!isOp(exp[j]))

		{

			while(exp[j]>='0'&&exp[j]<='9')

			{

				postexp[i++]=exp[j];

				j--;

			}

			postexp[i++]='#';

		}else

			switch(precedeT(exp[j],op->data[op->top]))

		{

			case -1:

				op->data[++op->top]=exp[j];

				j--;

				break;

			case 0:

				op->top--;

				j--;

				break;

			case 1:

				postexp[i++]=op->data[op->top--];

				break;

		}

	}

	while(op->data[op->top]!='=')

	{

		postexp[i++]=op->data[op->top--];

	}

	postexp[i]='\0';

	

}



float compvalue(char *postexp)

{

	typedef struct

	{

		float data[MaxSize];

		int top;

	}OP;



	float a,b,c,d;

	OP *st = (OP *)malloc(sizeof(OP));

	st->top=-1;

	while(*postexp!='\0')

	{

		switch(*postexp)

		{

		case '+':

			a=st->data[st->top--];

			b=st->data[st->top--];

			c=a+b;

			st->data[++st->top]=c;

			break;

		case '-':

			a=st->data[st->top--];

			b=st->data[st->top--];

			c=b-a;

			st->data[++st->top]=c;

			break;

		case '*':

			a=st->data[st->top--];

			b=st->data[st->top--];

			c=b*a;

			st->data[++st->top]=c;

			break;

		case '/':

			a=st->data[st->top--];

			b=st->data[st->top--];

			if(a!=0)

			{

				c=b/a;

				st->data[++st->top]=c;

			}

			else

			{

				printf("\0除零错误!\n");

				exit(0);

			}

			break;

		default:

			d=0;

			while(*postexp>='0'&&*postexp<='9')

			{

				d=10*d + *postexp - '0';

				postexp++;

			}

			st->data[++st->top]=d;

			break;

		}

		postexp++;

	}

	return st->data[st->top];

}



float compvalueT(char *postexp)

{

	typedef struct

	{

		float data[MaxSize];

		int top;

	}OP;



	float a,b,c,d;

	OP *st = (OP *)malloc(sizeof(OP));

	st->top=-1;

	while(*postexp!='\0')

	{

		switch(*postexp)

		{

		case '+':

			a=st->data[st->top--];

			b=st->data[st->top--];

			c=a+b;

			st->data[++st->top]=c;

			break;

		case '-':

			a=st->data[st->top--];

			b=st->data[st->top--];

			c=a-b;

			st->data[++st->top]=c;

			break;

		case '*':

			a=st->data[st->top--];

			b=st->data[st->top--];

			c=a*b;

			st->data[++st->top]=c;

			break;

		case '/':

			a=st->data[st->top--];

			b=st->data[st->top--];

			if(b!=0)

			{

				c=a/b;

				st->data[++st->top]=c;

			}

			else

			{

				printf("\0除零错误!\n");

				exit(0);

			}

			break;

		default:

			d=0;

			while(*postexp>='0'&&*postexp<='9')

			{

				d=10*d + *postexp - '0';

				postexp++;

			}

			st->data[++st->top]=d;

			break;

		}

		postexp++;

	}

	return st->data[st->top];

}



int _tmain(int argc, _TCHAR* argv[])

{



	char exp[]="1+((2+3)*4)-5";

	//char expT[]="1+((2+3)*4)-5";

	

	

	

	//fanzhuan(exp,expT);

	//printf("expT:%s\n",expT);



	char postexp[MaxSize];

	char postexpT[MaxSize];

	trans(exp,postexp);

	



	printf("中缀表达式:%s\n",exp);

	printf("后缀表达式:%s\n",postexp);

	transT(exp,postexpT);

	printf("前缀表达式:%s\n",postexpT);

	printf("后缀表达式的值:%f\n",compvalue(postexp));

	printf("前缀表达式的值:%f\n",compvalueT(postexpT));



	return 0;

}

 

哈哈,上面的代码已经包括中缀转前后缀和前后缀的求值算法实现了。

前缀和后缀表达式转换方法的区别主要在,后缀是从左往右扫描exp,前缀反之。所以两者的左右运算符的划分是相反的。这一点还体现在求值的时候。

 

好吧,弄好一篇了    2012-07-12

你可能感兴趣的:(表达式)