栈的运用——四则表达式求值(逆波兰表达式)及代码实现

栈的一个重点基础运用就是,四则表达式的求值,这里面困难在于,乘除在加减后面,却要先运算,加入括号后,就变的更加复杂。

波兰逻辑学家想到了一种不需 要括号的后缀表达法,我们也把它称为逆波兰(Reverse Polish Notation, RPN)表示。

对于9+(3-1)*3+10/2,如果用后缀表达式,则为:9 3 1 - 3 * +10 2 / +。我们先来看看用后缀表达式计算机如何求其值。

一、后缀表达式计算过程

规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果

计算过程,初始化一个空栈,前三个都为数字,于是压入,9 3 1,遇到 - 号,被减数3,减数1出栈进行计算,结果为2,此时压入2,接着3入栈,又遇到 * 号,2,3出栈计算,结果为6,6入栈,下面是+ 号,9,6出栈,相加,结果为15,入栈。10,2入栈,遇到 / 号,将两数出栈计算,结果为5,入栈,最后是+ 号,栈中15,5计算,结果为20,而20就是答案。

果然,后缀表达式可以轻松解决问题。那么我们需要得到后缀表达式。

规则:

  • 如果当前元素为操作数,则将该元素直接存入到后缀表达式中
  • 如果当前元素为“(”,则将其直接入栈;如果为“)”,则将栈中的操作符弹栈,并将弹栈的操作符存入到后缀表达式中,直至遇到“(”,将“(”从栈中弹出,并不将其存入到后缀表达式中
  • 如果是其他操作符,如果其优先级高于栈顶操作符的优先级,则将其入栈,如果是小于或等于栈顶操作符优先级,则依次弹出栈顶操作符并存入后缀表达式中,直至遇到一个栈顶优先级小于当前元素优先级时或者栈顶元素为“(”为止,保持当前栈顶元素不变,并将当前元素入栈;

依旧拿上面的 9+(3-1)*3+10/2 分析:

遍历,9输出,+ 栈中为空,入栈,左括号入栈
3输出,- 不高于 + ,入栈,1 输出,当前输出9 3 1,栈中+ ( -
右括号,- ,(出栈,遇到左括号,输出为9 3 1 -, 栈中+
符号* 优先级大于+ ,入栈,3输出,当前输出为9 3 1 - 3,栈中+ *
遇到+,优先级小于,等于+,出栈,+出栈,+入栈,栈中+,输出为9 3 1 - 3 * +
10输出,/ 优先级大于+,/ 入栈,当前输出为9 3 1 - 3 * + 10 ,栈中+ /
2 输出,栈中输出,得到最终结果。 9 3 1 - 3 * + 10 2 / +

二、代码实现

下面的代码只是支持一些简单的整数的加减乘除运算,而且不支持浮点数,负数或者数字大于9的数字的运算。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<stack>
using namespace std;
stack< int > q; //算数用的栈
char suffix[30];//后缀表达式
stack< char > p;//符号的栈
void solve() 
{
	for (int i = 0;i<strlen(suffix) ; i++){
		if (suffix[i] >= '0' && suffix[i] <= '9')
			q.push(suffix[i] - '0');
		else {
			int a, b,c;
			a = q.top();
			q.pop();
			b = q.top();
			q.pop();
			if (suffix[i] == '*')
				c = b * a;
			else  if (suffix[i] == '/')
				c = b / a;
			else if (suffix[i] == '+')
				c = b + a;
			else
				c = b - a;
			q.push(c);
		}
	}
	cout << "结果是" << q.top() << endl;
}

void change(char s[]) //后缀表达式求
{ 
	int j = 0;
	for (int i = 0; s[i] != '\0'; i++)
	{
		if (s[i] >= '0' && s[i] <= '9')
			suffix[j++] = s[i];
		else{
			if (p.size() == 0 || s[i] == '(')
				p.push(s[i]);
			else
			{
				if (s[i] == ')'){
					while (p.top() != '('){
						suffix[j++] = p.top();
						p.pop();
					}
					p.pop();//左括号不输出
				}
				else if (s[i] == '+' || s[i] == '-'){
					while (p.top()!='(') {
                   //对于加减,只有遇到括号才停止弹出
						suffix[j++] = p.top();
						p.pop();
						if (p.size() == 0||p.top()=='(')
							break;
					}
					p.push(s[i]);
				}
				else if (s[i] == '*' || s[i] == '/'){
					while (p.top()=='*'||p.top()=='/'){
					//当栈顶为乘除必定弹出,遇到加减括号则停止
						suffix[j++] = p.top();
						p.pop();
						if (p.size()== 0)
							break;
					}
					p.push(s[i]);
				}
			}
		}
	}
	while (p.size() != 0){ //将最后的弹出
		suffix[j++] = p.top();
		p.pop();
	}
	cout << suffix << endl;}
int main(){
	char s[30];
	cin >> s;
	change(s);
	solve();
}

猜你喜欢

转载自www.cnblogs.com/lonely-ok/p/12663374.html