算術表達式求值

中綴表達式

      我們平時寫的表達式稱爲中綴表達式。

      eg: 1. 2 - 3*4 +5       2.  2* (3- 5) +7

      正如上面的表達式,我們在計算的過程中,首先要注意運算符的優先級,其次要注意括號。 我們應如何判斷運算符的優先級以及如何進行運算。

後綴表達式

     首先,我們可以將中綴表達式轉化爲後綴表達式(逆波蘭表達式),然後進行運算。如何將中綴表達式轉化爲後綴表達式呢?規則如下:

     將上面的中綴表達式轉化爲後綴表達式:1. 2 3 4 *  - 5 +     2. 2 3 - 5 * 7 +

後綴表達式如何進行計算

     藉助棧,依次遍歷後綴表達式,當遇到操作數時,直接進行入棧。當遇到操作符時,彈出棧中的兩個元素,依次作爲右操作數和左操作數,將計算後的結果壓入棧中。最後棧中剩餘的元素,則爲表達式的值。

代碼實現:

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

//判斷是操作符還是操作數
enum Cal_Type
{
	OP_NUM,
	OP_SYMBOL,
};

struct Cell
{
	Cal_Type _type;//計算類型
	int _value;
	Cell(const Cal_Type& t, const int& x)
		:_type(t)
		,_value(x)
	{}
};

class Calculator
{
public:
	Calculator(const vector<int> &exp)
		:_infix(exp)
	{}

	int Count()
	{
		Transition(); //將中綴表達式轉化爲後綴表達式
		stack<int> num; //中間計算過程中的操作數
		int n = _exp.size();
		for(int i=0; i<n; ++i)
		{
			Cell cur = _exp[i];
			if(cur._type == OP_NUM)
			{
				num.push(cur._value);
			}
			else if(cur._type == OP_SYMBOL)
			{
				int d2 = num.top(); //右操作數
				num.pop();
				int d1 = num.top(); //左操作數
				num.pop();
				int sum = 0;

				switch(cur._value)
				{
				case '+':
					{sum = d1+d2;}
					break;
				case '-':
					{sum = d1-d2;}
					break;
				case '*':
					{sum = d1*d2;}
					break;
				case '/':
					{sum = d1/d2;}
					break;
				default:
					break;

				}
				num.push(sum);
			}
		}
		return num.top();
	}

	//判斷是否爲操作符
	bool IsTypied(char op)
	{
		switch(op)
		{
		case '-':
		case '+':
		case '*':
		case '/':
			return true;
		default:
			return false;
			break;
		}
	}

	//確定操作符的優先級
	int Priority(char op)
	{
		switch(op)
		{
		case '-':
		case '+':
			return 1;
		case '*':
		case '/':
			return 2;
		default:
			break;
		}
		return -1;
	}

	//中綴轉後綴表達式
	void Transition()
	{
		stack<int> tmp; //用於保存遇到‘(’時的運算符
		for(int i=0; i<_infix.size(); ++i)
		{
			if((_infix[i]+48)>='0' && (_infix[i]+48)<='9')//當遇到數字時,直接插入後綴表達式中
			{
				Cell c(OP_NUM,_infix[i]);
				_exp.push_back(c);
			}
			else if(_infix[i] == '(')
			{
				tmp.push(_infix[i]);
			}
			else if(_infix[i] == ')')
			{
				while(tmp.top() != '(')
				{
					_exp.push_back(Cell(OP_SYMBOL,tmp.top()));
					tmp.pop();
				}
				tmp.pop();
			}
			else if(IsTypied(_infix[i])) //如果爲運算符,應該判斷優先級
			{
				if(tmp.empty() || Priority(_infix[i]) > Priority(tmp.top()))//如果tmp爲NULL的話,只需要判斷棧頂元素和_infix[i]的優先級
				{
					tmp.push(_infix[i]);
				}
				else
				{
					while(!tmp.empty() && Priority(_infix[i]) <= Priority(tmp.top()))
					{
						_exp.push_back(Cell(OP_SYMBOL,tmp.top()));
						tmp.pop();
					}
					tmp.push(_infix[i]);
				}
			}
			else
			{
				cout<<"輸入有誤"<<endl;
				_exp.clear();
				return ;
			}
		}

		//如果tmp 不爲NULL的話,全部壓入_exp中
		while(!tmp.empty())
		{
			_exp.push_back(Cell(OP_SYMBOL,tmp.top()));
			tmp.pop();
		}
	}

private:
	vector<int> _infix; //中綴表達式
	vector<Cell> _exp;  //後綴表達式
};

void Test()
{
	int a[] = {2,'-',3,'*',4,'+',5};
	vector<int> exp(a,a+sizeof(a)/sizeof(a[0]));
	Calculator c(exp);
	cout<<c.Count()<<endl;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章