1. 程式人生 > >演算法學習-逆波蘭表示式RPN

演算法學習-逆波蘭表示式RPN

Reverse Polish Notation,即字尾表示式。

習慣上,二元運算子總是置於與之相關的兩個運算物件之間,即中綴表達方法。波蘭邏輯學家xxxxxxx於1929年提出了運算子都置於其運算物件之後,故稱為字尾表示式。

如:中綴表示式:a+(b-c)*d

        字尾表示式:abc-d*+

事實上,二元運算的前提下,中綴表示式可以對應一顆二叉樹(中序遍歷);逆波蘭表示式即該二叉樹後續遍歷的結果如上面給出的兩個例子可以通過如下圖所示的二叉樹得到


該結論對多元運算也成立,如“費運算”等

逆波蘭表示式的計算

計算給定的逆波蘭表示式的值。有效操作只有+-*/,每個運算元都是整數。

如:

“2“,”1”,“+”,“3”,“*”:9-------------(2+1)*3

“4”,“13”,“5”,“/”,“+”:6---------------4+(13/5)

拿到運算元的時候直接入棧,遇到操作符將前兩個數出棧進行運算,運算結果入棧,然後繼續。

程式碼如下

bool IsOperator(const char* token)
{
	return ((token[0] == '+') || (token[0] == '-')
		|| (token[0] == '*') || (token[0] == '/'));
}

int ReverSePolishNotation(const char* str[], int size)
{
	std::stack<int> s;
	int a, b;
	const char* token;
	for (int i = 0; i < size; i++)
	{
		token = str[i];
		if (!IsOperator(token))
		{
			s.push(atoi(token));
		}
		else
		{
			b = s.top();
			s.pop();
			a = s.top();
			s.pop();
			if (token[0] == '+')
			{
				s.push(a + b);
			}
			else if (token[0] == '-')
			{
				s.push(a - b);
			}
			else if (token[0] == '*')
			{
				s.push(a * b);
			}
			else if (token[0] == '/')
			{
				s.push(a / b);
			}
		}
	}
	return s.top();
}

int _tmain(int argc, _TCHAR* argv[])
{
	const char* str[] = {"2", "1", "+", "3", "*"};
	int value = ReverSePolishNotation(str, sizeof(str) / sizeof(const char*));
	std::cout<<value<<std::endl;
	system("pause");
	return 0;
}

  • 計算數學表示式的最常用方法
  • 在實踐中往往給出的不是立即數,而是變數名稱,若經常計算且表示式本身不變,可以事先將中綴表示式轉換成逆波蘭表示式儲存。