[data structure] - inverse Polish expression

Introduction to inverse Polish expression

        Suppose that one day, Zhao dizuo (whose name is purely fictional, if similar, it is purely coincidental) finds his classmate Zhang San with four arithmetic problems with extremely terrible data, hoping that he can give the answer within 1s. What is the best way at this time? Of course, he ignored him. Unfortunately, Zhang San, who was willing to explore, was not willing to give up this opportunity, so he took out his laptop.

        To solve this problem, let's abstract the expressions of the four operations as much as possible:

ans=A+B/C+(D*E+F)*G

        Mathematical expressions written naturally in line with people's cognitive habits are called infix expressions. Unfortunately, stupid computers can't directly recognize this expression, which means that we must do some work so that the computer can calculate from left to right and get the correct result.

      One solution is to convert infix expression into suffix expression (inverse Polish expression).

      Inverse Polish formula is a formula that writes the quantity to be calculated in front and the operator in the back (usually after two numbers), such as:

Infix expressionReverse Polish notation
A + BA B +
A * BA B *
A +B * CA B C * +
A * ( B + C )A B C + *

Solution of inverse Polish equation

The inverse Polish solution process can be realized by stack. For ease of understanding, take an example with values:

Infix expression: 6 * ((5 + (2 + 3) * 8) + 3)

First, it is transformed into inverse Polish: 6 5 2 3 + 8 * + 3 +*

The calculation process is as follows:

First, put the first four numbers on the stack in sequence:

Top Of Stack --->3
2
5
6

Then, when the first symbol is a plus sign, record and pop up the two elements at the top of the stack, and press the calculation result into the stack

Top Of Stack --->5
5
6

Continue the operation. If you encounter a number, press it into the stack. If you encounter a symbol, pop up the two elements at the top of the stack and press the result.

(special note: in the calculation of subtraction and division, the number pop-up order is just opposite to its calculation order)

Top Of Stack --->288

The calculation is completed, and the result is 288.

After a brief understanding of the calculation principle, start to write code happily (the code is given in the form of function for easy handling):

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

long long calculate(string str)
{
	int len=str.length(),pos=0;
	stack<long long> sta;
	char ch;
	
	while(pos<len)
	{
		if(str[pos]>='0'&&str[pos]<='9')
		{
			long long temp=0;
			while(str[pos]!=' '&&str[pos]!='.') temp=temp*10+(str[pos++]-'0');
			sta.push(temp);
		}
		else if(str[pos]==' '||str[pos]=='.') pos++;
		else if(str[pos]=='@') break;
		else
		{
			ch=str[pos++];
			int num1,num2;
			num2=sta.top(); sta.pop();
			num1=sta.top(); sta.pop();
			
			switch(ch)
			{
				case '+': sta.push(num1+num2); break;
				case '-': sta.push(num1-num2); break;
				case '*': sta.push(num1*num2); break;
				case '/': sta.push(num1/num2); break;
			}
		}
	}
	return sta.top();
}

int main()
{
	getline(cin,str);
	cout<<calculate(str);
	return 0;
}

Infix expression and transformation of inverse Polish

Recommend a big man's blog (much clearer than I said) Infix expression to suffix expression

The overall idea still adopts the stack method (take 3 * (2 + 1) as an example)  )

Preparation: use the string class to store the infix expression to be converted, and use two stacks to store and record numbers and symbols.

Main ideas:

  1. If a number is encountered, push it into the number stack
  2. If four operators and left parentheses are encountered, they are pushed into the symbol stack
  3. If you encounter a right parenthesis, start the inspection from the top of the current symbol stack, and keep pushing the symbol into the number stack until you encounter the first left parenthesis. But at the same time, discard the left parenthesis in the symbol stack.
  4. Finally, after the string is scanned, the remaining symbols in the current symbol stack are pressed into the number stack in turn.

Main steps:

  1. The number 3 is detected and pressed directly into the number stack
  2. The current character is' * ', which is pushed into the symbol stack
  3. The current character is' (', which is pushed into the symbol stack
  4.  ( The middle two numbers are omitted with a '+' sign, and the practice is exactly the same)
  5. When a closing bracket is encountered, press' + 'in the symbol stack into the number stack

Specific implementation code:

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

string TRANS_TO_POLISH(string str)
{
	stack<string> num, oper;
	int len = str.length(), pos = 0;

	while (pos < len)
	{
		if (str[pos] >= '0' && str[pos] <= '9')
		{
			long long temp = 0;
			while (str[pos] >= '0' && str[pos]<='9') temp = temp * 10 + (str[pos++] - '0');
			num.push(to_string(temp));
		}
		else if (str[pos] == ' ' || str[pos] == '.') pos++;
		else
		{
			char ch = str[pos++];
			if (ch == '+') oper.push("+");
			else if (ch == '-') oper.push("-");
			else if (ch == '*') oper.push("*");
			else if (ch == '/') oper.push("/");
			else if (ch == '(') oper.push("(");
			else
			{
				while (oper.top() != "(")
				{
					num.push(oper.top());
					oper.pop();
				}
				oper.pop();
			}
		}
	}
	while (!oper.empty()) { num.push(oper.top()); oper.pop(); }

	string ans = "";
	while (!num.empty()) ans = num.top() + " "+ans, num.pop();
	return ans;
}

int main()
{
	string str; getline(cin, str);
	cout << TRANS_TO_POLISH(str);
	return 0;
}

Tags: C++ data structure

Posted on Fri, 03 Sep 2021 15:01:38 -0400 by Swerve1000