表达式求值

表达式求值

以求解2+5*(3-2)为例,按照数据结构课本上的思路,是创建两个栈,一个数字栈,一个符号栈,然后根据入栈的符号的优先级来不断出栈进行计算,理解起来是挺方便的,但是代码记起来有点复杂,尤其是还需要两个栈。
近日看了一个老师的另外一种解法,利用递归的方式解决,不需要利用栈,听起来贼神奇,并且也是比较好理解和记忆的,下面介绍下另外一个老师的方法。
对于表达式2+5*(3-2)而言,我们先判断这是一个什么式子,按照以往的经验,我们会说这是一个加法式,因为加法运算是这个式子中最后计算的。 ”+“把式子分为左右两部分,左边2,右边5 x(3-2);接着看右边这个式子,我们可以判断这是一个乘法式,判断方式如上;**” * “**也同样把式子分为两部分,左边为5,右边为(3-2);那求解最开始的综合式是否可以理解为f=a (operator) b,此处的operator可以是+、-、*、/中的任何一种情况;其中 a 和 b 的结果的求解方式和 f 的一样,所以,这是一个递归的过程。
确定递归求解的边界和递归过程:

递归边界

//此时表明输入的表达式不存在运算符,都是数字
if (op == -1) {
//			int num = 0;
//			for (int i = l; i < r; i++)
//			{
//				if (str[i]<'0' || str[i]>'9')
//					continue;
//				num = num * 10 + str[i] - '0';
//			}
//			return num;
}

递归过程,即逐步求解 a 与 b 的过程
此时该如何确定operator的位置?根据我们以往的经验,对一个综合式,计算顺序为先乘除后加减,右括号先计算括号里面的,所以先运算运算符最高的,对于我们开始的例子,应该是先计算(3-2);我们再回过来看开始的例子,例子的运算顺序是 -、*、+,然而递归的顺序是先开始的后返回,和入栈出栈的顺序很想,先入后出,所以我们先找运算符中优先级最低的,找到后确定左右的式子 a 和 b。然后再逐步确定 a 和 b 中的最低运算符,直到遍历完字符串的所有元素,

代码如下:

//定义两个变量 pri、cur_pri 记录先前运算符和当前运算符的高低,因为我们要找出运算符最低的那一个
//因为括号会改变运算符的顺序,定义一个变量 temp 来改变运算符的高低
int calc(char *str,int l,int r){
	int op=-1; //记录最低操作符的初始位置 
	int pri=INF-1; //先前运算符的优先级
	int cur_pri; //记录当前符号优先级
	int temp=0; //定义括号改变运算符的变量
	for(int i=l;i<r;i++){
		cur_pri=INF;//定义当前运算符的初始大小
		switch(str[i]){
		//如果是运算符,则相应的改变当前运算符的大小
		case '(':
			temp +=100;
			break;
		case ')':
			temp -=100;
			break;
		case '+':  //此处是体现的case 并列,意味着case '+' 与下面的 case '-'执行相同的操作;直到遇到break;
		case '-': 
			cur_pri = 1 + temp; 
			break; 
		case '*':
		case '/': 
			cur_pri = 2 + temp; 
			break;
		}
		//如果当前运算符优先级小于等于先前的运算符优先级,则替换
		if (cur_pri <= pri) {
			//将op 指到当前的字符串字符的位置
			op = i;
			pri = cur_pri;
		}
	//根据op 的位置确定 a 和 b 
	int a = calc(str, l, op);
	int b = calc(str, op + 1, r);
	switch (str[op]) {
		case '+': return a + b;
		case '-': return a - b;
		case '*': return a * b;
		case '/': return a / b;
	}
	return 0;
	}

如有不同见解,欢迎讨论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值