中缀表达式转后缀表达式并求值讲解(源码)

中缀表达式转后缀表达式并求值讲解(源码)

我自己比较清楚刚学的时候的敲代码的无从下手的感觉,所以下面有源代码
如果清楚转换的规则,直接去看代码
不然还是,先捋清楚规则,在看代码,否则看不懂

中缀表达式转后缀表达式,手写的话很简单,用括号法就可以,下面随便找一个式子

(a+b+c*d)/e

为什么找这样一个式子呢?
因为它可以解释一个问题,就是中缀表达式转后缀表达式,结果不唯一
①根据运算顺序加括号
( ( ( a + b ) + ( c * d ) ) / e )
②把运算符移到相应括号的后面
( ( ( a b ) + ( c d ) * ) + e) /      注意中间的那个“+”不是原来的,看颜色区分
那么结果就是
"a b + c d * + e / "
下面我们换一个运算顺序
这样加括号 ( ( a + ( b + ( c * d ) ) )/ e )
那么结果就会变成
"a b c d * + + e / "

手写就是这么简单,但是计算机转化却没这么容易,因为没有人这么智能。


中缀用栈转后缀的规则

对于计算机来说,式子求值更好算的是后缀表达式,我们一般中缀表达式转为后缀表达式,
采用栈来完成
用代码转化之前,首先得知道代码转化过程中的规则
一般需要两个栈,一个用来过渡s1,一个存储结果s2,还有一个中缀表达式的字符数组mid(有数字有字符,所以使用字符数组)
规则:①如果当前mid[i]是数字,直接进入结果栈
    ②如果mid[i]是 ’ ( ',直接进入过程栈
    ③如果mid[i]是“+ - * / ”,那么就要进行判断(1和2是或的关系)
    1.如果当前过程栈s1是空的,即top1==-1,mid[i]直接进入过程栈s1
    2.如果当前mid[i]运算符的优先级大于s1栈顶的运算符优先级,直接进入过程栈s1
    3.如果当前mid[i]运算符的优先级小于等于于s1栈顶的运算符优先级,则对s1进行出栈存到s2,直到mid[i]的优先级大于s1的栈顶。然后将mid[i]存到s1。
    ④如果当前mid[i]是 ’ ) ',则对s1进行出栈存到s2,直到遇见‘( ’, ‘(’直接出栈,不存到s2

    
    最后输出s2就可以了

下面直接看源码,我根据自己的理解所写,可能会有所冗余

#include<iostream>
#include<cstdio>
#define maxSize 20

using namespace std;

int com(char c)					//判断优先级的函数
{
	if(c=='*'||c=='/')
		return 2;
	else if(c=='+'||c=='-')
		return 1;
	else if(c=='(')
		return 0;
}
void change(char mid[],char s2[],int &top2)		//中缀转后缀的函数
{												//因为需要输出s2,记录top2的改变,所以top2用引用传参
	char s1[maxSize];int top1=-1;				//定义过程栈
	int i=0;
	while(mid[i]!='\0')
	{
		if(mid[i]>='0'&&mid[i]<='9')
		{
			s2[++top2]=mid[i];
			i++;								//每一次处理完当前的mid【i】,要i++,不要忘记
		}
		else if(mid[i]=='(')
		{
			s1[++top1]=mid[i];
			i++;
		}
		else if(mid[i]=='+'||mid[i]=='-'||mid[i]=='*'||mid[i]=='/')
		{
			if(top1==-1||s1[top1]=='('||com(mid[i])>com(s1[top1]))
			{
				s1[++top1]=mid[i];
			}
			else
			{
				while(com(mid[i])<=com(s1[top1]))
				{
					s2[++top2]=s1[top1--];
				}
				s1[++top1]=mid[i];
			}
			i++;
		}
		else if(mid[i]==')')
		{
			while(s1[top1]!='(')
			{
				s2[++top2]=s1[top1--];
			}
			top1--;
			i++;
		}	
	}
	while(top1!=-1)
	{
		s2[++top2]=s1[top1--];				//如果处理完mid【i】,s1不为空,全部出栈存到s2
	}
}
int main()
{
	char mid[20];char s2[20];int top2=-1;
	gets(mid);
	change(mid,s2,top2);
	int i=0;
	while(i!=top2+1)						//输出s2
	{
		cout<<s2[i++];
	}
	return 0;
} 

全部代码就是这样。

后缀表达式求值

后缀表达式求值,一般都是用栈来完成的,且运算数都是一位
过程也很简单从左到右依次遍历后缀表达式,遇到数字直接压入栈中,遇到运算符,依次取出栈顶的两个数字,进行运算。先出来的是右运算数,次之是左云算数
下面是源码

#include<iostream>
#include<cstdio>
#define maxSize 30
using namespace std;
int com(int a, char op, int b)
{
	if(op=='+')
		return a+b;
	else if(op=='-')
		return a-b;
	else if(op=='*')
		return a*b;
	else if(op=='/')
	{
		if(b==0)				//除数是0的情况需要判断
		{
			cout<<"error";
			return 0;
		}
		else
			return a/b;
	}
}
int cal(char bh[])
{
	int i=0,a,b;
	char op;
	int stack[maxSize];
	int top=-1;
	while(bh[i]!='\0')
	{
		if(bh[i]>='0'&&bh[i]<='9')
		{
			stack[++top]=bh[i]-'0';			//将字符数字转换成整数类型压入栈中
			i++;
		}	
		else
		{
			op=bh[i];						//遇到运算符
			b=stack[top--];					//取出数字
			a=stack[top--];
			stack[++top]=com(a,op,b);		//调用运算函数,将计算结果压入栈中
			i++;
		}
	}
	return stack[top];
}
int main()
{
	char bh[maxSize];
	gets(bh);
	int result=cal(bh);
	cout<<result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值