zoukankan      html  css  js  c++  java
  • 前缀中缀后缀表达式

     

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

    一.表达式的三种形式:

    中缀表达式:运算符放在两个运算对象中间,这是我们书写的时候最熟悉的一种形式,如:(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

  • 相关阅读:
    Windows下MongoDB安装与PHP扩展
    仿Smarty替换模板标签时遇到的问题
    class ha_innobase: public handler
    类handler
    类Item_field
    函数buf_pool_init_instance
    函数buf_pool_init
    安装php,nginx 带debug
    gdb调试SAPI方式的php
    重启php-fpm
  • 原文地址:https://www.cnblogs.com/woainilsr/p/2587304.html
Copyright © 2011-2022 走看看