Reverse Poland of C++ Basic Algorithm

Reverse Polish Algorithm

Reverse Polish (Reverse Polish Notation, RPN, or reverse Polish notation), also known as suffix expression (write the operator after the operand).

So what is postfix expression.

**Infix:**a+b

Prefix (Poland): +ab

**Suffix (Reverse Polish): **ab+

infix --> prefix

  • Add brackets: (a+b), from left to right, () represents an expression, when an operator is encountered, bracket the expressions on both sides until the end
  • Extract symbols by parenthesis: the operator in the most open parenthesis is mentioned before the opening parenthesis , just before the parenthesis
  • Finally, the reverse Polish expression is obtained

( a +b ) * c + d - ( e + g ) * h

((((a + b) * c ) + d ) -( (e+g)) * h))

-+*+abcd*+egh

infix --> suffix

  • Add brackets: (a+b), from left to right, () represents an expression, when an operator is encountered, bracket the expressions on both sides until the end
  • Extract symbols by parenthesis: the operator in the most open parenthesis is mentioned before the closing parenthesis
  • Finally, the reverse Polish expression is obtained

( a +b ) * c + d - ( e + g ) * h

((((a + b) * c ) + d ) -( (e+g)) * h))

ab+c*d+eg+h*-

Code Implementation Ideas

A simple implementation idea provided here

Infix to suffix

  1. Initialize two stacks: s1, s2

  2. Scan expressions from left to right

  3. When an operand is encountered, push into s1

  4. encountered operator

    • If s2 is empty, or the top of the stack is ( , push it directly to the stack
    • If the priority is higher than the operator on the top of the stack, also push s2
    • Otherwise, push the operator in s2 into s1, and go to 4
  5. If it encounters ), push the operator in s2 into s1 until it encounters (, discard ()

  6. Finally, push all the remaining s2 into s1

#include<iostream>
#include<sstream>
#include<stack>
#include<vector>
#include<map>

using namespace std;




int IsOper(char str, const vector<char> &oper) {
    
    
	for (int i = 0; i < oper.size(); i++) {
    
    
		if (oper[i] == str) return i;
	}
	return -1;
}

void Excharge(stack<char> &s2, stack<char> &s1) {
    
    
	while (!s2.empty()) {
    
    
		s1.push(s2.top());
		s2.pop();
	}
}

void Excharge_(stack<char>& s2, stack<char>& s1) {
    
    
	while (!s2.empty() && s2.top() != '(') {
    
    
		s1.push(s2.top());
		s2.pop();
	}
	if (s2.empty()) return;
	s2.pop();
}

void Show(stack<char> s1) {
    
    

	if (s1.empty()) {
    
    
		cout << endl;
		return;
	}
	char val = s1.top();
	s1.pop();
	Show(s1);
	cout << val;  
}

void ReversePolish(string expression) {
    
    
	stack<char> s1;
	stack<char> s2;
	vector<char> oper = {
    
     '*','/','+','-','(',')' };
	map<char, int> rank;
	rank['('] = 3;
	rank['*'] = 2;
	rank['/'] = 2;
	rank['+'] = 1;
	rank['-'] = 1;
	for (int i = 0; i < expression.size(); i++) {
    
    
		int ret = IsOper(expression[i], oper);
		if (ret < 0) {
    
    
			s1.push(expression[i]);   //压入栈内
		}
		else {
    
    
			if (s2.empty() || s2.top() == '(') {
    
    
				s2.push(expression[i]);
			}
			else if (expression[i] == ')') {
    
    
				Excharge_(s2, s1);
			}
			else if (rank[expression[i]] > rank[s2.top()]) {
    
    
				s2.push(expression[i]);
			}
			else {
    
    
				Excharge(s2, s1);
				s2.push(expression[i]);   // 栈为空,直接压入s2
			}
		}
	}
	Excharge(s2, s1);
	Show(s1);
}

int main(void) {
    
    

	ReversePolish("(1+2)*5");
	ReversePolish("1+2*5");
	ReversePolish("(a+b)*c+d-(e+g)*h");

	return 0;
}

Here I simply use a single character as a variable. If the number is two digits, an error will occur. , if the insertion value in the stack is divided from the beginning , the suffix calculation of more than two digits can be realized, but I have not tried it here. The main core is the principle of the reverse Polish algorithm.

The output is

12+5*
125*+
ab+c*d+eg+h*-

The above result is the generated suffix expression. Here, when s1 is pushed onto the stack, synchronous operations can be performed. The operation rules are as follows

Suffix calculation
1) A new stack s1 is created.
2) Compile postfix expressions.
3) Encounter a number and press it into s1.
4) When an operator is encountered, two numbers are directly output from pop for calculation, and then pushed into s1.
5) Finally know the end of the entire expression traversal.

Summarize

The core of the change from infix to suffix is ​​s2. We can think of s2 as a monotonically decreasing stack, but we don’t think so, because there are parentheses that can make the "priority" of ()some operators infinitely higher!

What I understand here is ()an overall scope, and the left parenthesis (can be regarded as the operator with the highest priority, which is also the beginning of the scope, while the right parenthesis )is the moment when the scope ends.

So if you look at it this way, there are still only high-priority operators on top, low-priority operators on the bottom, and the scope as a whole has the highest priority.

The function of using a monotonically decreasing stack is to find the first operator on the right side of the element with a priority lower than itself , and then operate on the previous value.


The old rules are useful Erlian, thank you all. . .

Guess you like

Origin blog.csdn.net/suren_jun/article/details/127462597