推免复习之数据结构与算法 栈计算器

下午花了一个多小时写了一个栈计算器,也算是对栈的应用的复习了,还记得大一的时候也写过这玩意,可是那时候我好像花的时间是两个下午。

在讲解这个栈计算器的大体思路前,我先讲解一下我实现的功能:能够对加减乘除四个运算符进行运算,支持对括号的运算,但是输入的数字只能在0-9之间,也就是只能是一位数,因为是从字符串里读取的,所以每次只能读一位,否则需要采用别的方法分解式子,这个问题不是这个栈计算器的重点,不做探讨。

我先来讲解一下这个栈计算器的大体思路:

  1. 从左到右对输入的式子进行扫描,只要是数字,就加入到操作数栈。

  2. 如果是运算符的话,就要对优先级进行比较了,如果该运算符比运算符栈栈顶元素的优先级要高,则直接入栈,否则,开始循环,每个循环都取出操作数栈的上两个元素,再取出运算符栈的栈顶元素,进行运算,再把结果压进操作数栈,直到碰到左括号,运算符栈已经为空或运算符栈顶元素比当前元素的优先级低这三种情况时,停止循环,把该元素压进运算符栈的栈顶。

  3. 遇到左括号直接进栈,遇到右括号则不入栈,而是开始对括号里的式子进行计算,计算规则很简单,每次从操作数栈取最上面的俩元素,再取运算符栈的栈顶元素,把计算结果再压入操作数栈,一直循环,直到碰到左括号则停止,把这个左括号出栈。

  4. 遍历完算式字符串,此时一个操作数栈,一个运算符栈已经满足后缀表达式的计算要求,只要一直循环计算就行了,每个循环和之前的一样,也是取操作数的栈顶部俩元素,再取运算符栈的栈顶元素,计算结果,再把结果压入操作数栈,直到运算符栈为空为止,此时,操作数栈只剩一个元素,也就是这个运算结果。

#include<iostream>
#include<stack>
#include<string>
using namespace std;

class stackCalculator
{
private:
	string formulas;
	stack<int> s_number;
	stack<int> s_operator;
public:
	bool inputFormulas()
	{
		cin >> formulas;
		return true;
	}
	int calculator()
	{
		int size = formulas.size();
		for (int i = 0; i < size; i++)
		{
			if (formulas[i] > 47 && formulas[i] < 58)
			{
				s_number.push(int(formulas[i])-48);
			}
			else if (formulas[i]=='+') //运算符
			{
				while ((!s_operator.empty())&&s_operator.top()!='(')
				{
					int var1 = s_number.top();
					s_number.pop();
					int var2 = s_number.top();
					s_number.pop();
					char ope = s_operator.top();
					s_number.push(getResult(var1,var2,ope));
					s_operator.pop();
				}
				s_operator.push('+');
			}
			else if (formulas[i] == '-') //运算符
			{
				while ((!s_operator.empty())&&s_operator.top()!='(')
				{
					int var1 = s_number.top();
					s_number.pop();
					int var2 = s_number.top();
					s_number.pop();
					char ope = s_operator.top();
					s_number.push(getResult(var1, var2, ope));
					s_operator.pop();
				}
				s_operator.push('-');
			}
			else if (formulas[i] == '*') //运算符
			{
				if (s_operator.empty() || s_operator.top() == '+' || s_operator.top() == '-')
				{
					s_operator.push('*');
				}
				else
				{
					while (s_operator.top()=='*'||s_operator.top()=='/')
					{
						int var1 = s_number.top();
						s_number.pop();
						int var2 = s_number.top();
						s_number.pop();
						char ope = s_operator.top();
						s_number.push(getResult(var1, var2, ope));
						s_operator.pop();
					}
					s_operator.push('*');
				}
			}
			else if (formulas[i] == '/') //运算符
			{
				if (s_operator.empty() || s_operator.top() == '+' || s_operator.top() == '-')
				{
					s_operator.push('/');
				}
				else
				{
					while (s_operator.top() == '*' || s_operator.top() == '/')
					{
						int var1 = s_number.top();
						s_number.pop();
						int var2 = s_number.top();
						s_number.pop();
						char ope = s_operator.top();
						s_number.push(getResult(var1, var2, ope));
						s_operator.pop();
					}
					s_operator.push('/');
				}
			}
			else if(formulas[i]=='(')
			{
				s_operator.push('(');
			}
			else if (formulas[i] == ')')  //直到匹配的左括号出栈为止
			{
				while (s_operator.top() != '(')
				{
					int var1 = s_number.top();
					s_number.pop();
					int var2 = s_number.top();
					s_number.pop();
					char ope = s_operator.top();
					s_number.push(getResult(var1, var2, ope));
					s_operator.pop();
				}
				s_operator.pop();
			}
			else
			{
				return 0;
			}
		}
		while (!s_operator.empty())
		{
			int var1 = s_number.top();
			s_number.pop();
			int var2 = s_number.top();
			s_number.pop();
			char ope = s_operator.top();
			s_number.push(getResult(var1,var2,ope));
			s_operator.pop();
		}
		if (s_operator.empty())
		{
			cout << "计算结果为:" << s_number.top() << endl;
		}
		else
		{
			cout << "计算失败,式子无效" << endl;
		}
		return 0;
	}
	int getResult(int var1, int var2, char oper)  //var1是先出栈的,var2是后出栈的
	{
		if (oper == '+')
		{
			return var2 + var1;
		}
		else if (oper == '-')
		{
			return var2 - var1;
		}
		else if (oper == '*')
		{
			return var2 * var1;
		}
		else if (oper == '/')
		{
			return var2 / var1;
		}
		else  //不包含我们的四种运算符
		{
			return 0;
		}
	}
};

int main()
{
	stackCalculator *sc = new stackCalculator();
	sc->inputFormulas();
	sc->calculator();
	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值