栈在表达式求值中的应用

栈在表达式求值中的应用

算数表达式:操作数、运算符、界限符
逆波兰表达式=后缀表达式
波兰表达式=前缀表达式

中缀转后缀手算方法:(后缀表达式不唯一)
1.确定中缀表达式中各个运算符的运算顺序
2.选择下一个运算符,按照[左操作数 右操作数 运算符]的方式组合成一个新的操作数
3.如果还有运算符没被处理,就继续2

私房菜:“左优先”原则,不要FreeStyle,保证手算和机算结果相同
“左优先”原则:只要左边的运算符能先计算,就优先算左边的

中缀转后缀手算方法:(后缀表达式唯一)
1.确定中缀表达式中各个运算符的运算顺序
2.选择下一个运算符,按照[左操作数 右操作数 运算符]的方式组合成一个新的操作数
3.如果还有运算符没被处理,就继续2
4.“左优先”原则:只要左边的运算符能先计算,就优先算左边的

中缀表达式转后缀表达式的机算方法:
初始化一个栈,用于保存暂时还不能确定运算顺序的运算符
从左到右处理各个元素,直到末尾。可能遇到三种情况:
1.遇到操作数。直接加入后缀表达式。
2.遇到界限符。遇到“(”直接入栈;遇到“)”则依次弹出栈内运算符并加入后缀表达式,直到弹出“(”为止。注意“(”不加入后缀表达式。
3.遇到运算符。依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到“(”或栈空则停止。之后再把当前运算符入栈。
按上述方法处理完所有字符后,将栈中剩余运算符依次弹出,并加入后缀表达式

void middleToLast(char middle[], int length, SqList &L){
	SqStack S;
	initStack(S);
	for(int i = 0; i < length; i++){
		if(middle[i] == "("){//界限符处理
			push(S,middle[i]);
		}else if(middle[i] == ")"){//界限符处理
			char topElem = getHeadElem(S);
			while(topElem != "("){
				pop(S, topElem);
				listInsert(L, topElem);
			}
			if(topElem == "("){
				pop(S, topElem);
			}
		}else if(middle[i] == "+" || middle[i] == "-" || middle[i] == "*" || middle[i] == "/"){//操作符处理
			char topElem = getHeadElem(S);
			while(operatorPriority(middle[i],topElem) && topElem != "(" && !stackEmpty(S)){
				pop(S, topElem);
				listInsert(L, topElem);
			}
			push(S, middle[i]);
		}else{//操作数处理
			listInsert(L, middle[i]);
		}
	}
	if(!stackEmpty(S)){
		char topElem;
		pop(S, topElem);
		listInsert(L, topElem);
	}//循环完后栈非空时的处理
	return;
}
//判读运算符a的优先级是否不大于运算符b的优先级
bool operatorPriority(char a, char b){
	if((a == "+" || a == "-") && (b == "+" || b == "-" || b == "*" || b == "/")){
		return true;
	}else{
		return false;
	}
}

后缀表达式的手算方法:
从左往右扫描,每遇到一个运算符,就让运算符前面最近的两个操作数执行对应运算,合体为一个操作数
注意:两个操作数的左右顺序

后缀表达式的机算方法:(用栈(用于存放当前暂时还不能确定运算次序的操作数)实现后缀表达式的计算)
1.从左往右扫描下一个元素,直到处理完所有元素
2.若扫描到操作数则压入栈,并回到1;否则执行3
3.若扫描到运算符,则弹出两个栈顶元素,执行相应运算(注意:先出栈的是“右操作数”),运算结果压回栈顶,回到1

int lastCalculation(SqList L){
	
	for(int i = 0; i < L.length; i++){
		if(L.data[i] == "+" || L.data[i] == "-" || L.data[i] == "*" || L.data[i] == "/"){
			char topElem1,topElem2;
			pop(S, topElem2);
			pop(S, topElem1);
			int temp = calculate(topElem1, topElem2, L.data[i]);
		}else{
			push(S,(int)L.data[i]);
		}
	}
	return getHeadElem(S);
}
//计算
int calculate(int topElem1, int topElem2, char operate){
	if(operate == "+"){
		result1 = topElem1 + topElem2;
		return result1;
	}
	if(operate == "-"){
		result2 = topElem1 - topElem2;
		return result2;
	}
	if(operate == "*"){
		result3 = topElem1 * topElem2;
		return result3;
	}
	if(operate == "/"){
		result4 = topElem1 / topElem2;
		return result4;
	}
}

后缀转中缀的手算方法:前面的逆过程

中缀转前缀手算方法:(前缀表达式唯一)
1.确定中缀表达式中各个运算符的运算顺序
2.选择下一个运算符,按照[运算符 左操作数 右操作数]的方式组合成一个新的操作数
3.如果还有运算符没被处理,就继续2
4.“右优先”原则:只要右边的运算符能先计算,就优先算右边

前缀表达式的机算方法:(用栈实现前缀表达式的计算)
1.从右往左扫描下一个元素,直到处理完所有元素
2.若扫描到操作数则压入栈,并回到1;否则执行3
3.若扫描到运算符,则弹出两个栈顶元素,执行相应运算(注意:先出栈的是“左操作数”),运算结果压回栈顶,回到1

在这里插入代码片

中缀表达式的计算(用栈实现)
中缀转后缀+后缀表达式求值两个算法的结合

用栈实现中缀表达式的计算:
初始化两个栈,操作数栈运算符栈
若扫描到操作数,压入操作数栈
若扫描到运算符或界限符,则按照“中缀转后缀”相同的逻辑压入运算符栈(期间也会弹出运算符,每当弹出一个运算符时,就需要再弹出两个操作数栈的栈顶元素并执行相应运算,运算结果再压回操作数栈

在这里插入代码片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

和安韩Pro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值