[Data structure] C++ converts a well-written expression into reverse Polish

Question: Suppose an expression consists of a single-letter variable, a binocular operator, and parentheses (for example: "(a*(b+c)-d)/e)". Try writing an algorithm to convert a properly written expression into reverse Polish notation.

Step ideas:

(1) First, two stacks need to be allocated. Stack s1 is used to temporarily store operators (including an end symbol). This operator follows the principle that the higher the priority toward the top of the stack, the higher the priority in the stack; stack s2 is used to input inverse Polish style, for convenience, the stack s1 needs to put an operator with the lowest priority first, here it is assumed to be '#';

(2) Read the characters x one by one from the left end of the infix formula, and perform the following steps sequentially:

   1. If x is an operand, analyze the complete operand (here, for convenience, letters are used instead of numbers), and push x directly into the stack s2;

   2. If x is an operator, discuss according to the situation:

  •                         ①If x is '(', push it directly into the stack s1;
  •                       ②If x is ')', the operators between '(' closest to the top of stack s1 are popped out of the stack one by one, pushed into stack s2 one by one, and '(' is discarded at this time;
  •                         ③If x is an operator other than '(' and ')', discuss the following cases:
    •                                 ③-1 If the top element of the current stack s1 is '(', push x directly into the stack s1;
      •                                ③-2 If the top element of the current stack s1 is not '(', compare x with the top element of stack s1, if the priority of x is greater than the priority of the top operator of stack s1, push x directly into Stack s1. Otherwise, pop the top operator of stack s1 and push it into stack s2 until the priority of the top operator of stack s1 is lower than (excluding equal to) the priority of x, or the top of stack s2 The operator is '(', then push x onto the stack s1;

 (3) After (2), check whether the stack s1 is empty, if not, pop the elements in the stack one by one and push them into the stack s2 (excluding '#');      

 (4) After the above steps are completed, the stack s2 is the reverse Polish output result. But the stack s2 should be processed in reverse order, because the first character of the expression is at the bottom of the stack at this time;

Code:

#include <stack>
#include <iostream>
#include <string.h>
#include <algorithm>

using namespace std;

bool compare_precedence(char a, char b);
string RPN(string expression);

int main()
{
    cout <<"Please input the normal expression:" <<endl;
    string expression;
    cin >> expression;
    string RPN_result = RPN(expression);
    cout <<"The RPN of expression is: \n"<< RPN_result <<endl;
    return 0;
}

string RPN(string expression){
    stack<char> s1;//临时存储运算符
    s1.push('#');
    stack<char> s2;//输入逆波兰式
    for (decltype(expression.size()) index = 0; index != expression.size(); index++){
        char x = expression[index];
        if((x>='a'&& x<='z') || (x>='A' && x<='Z')){
            s2.push(x);
            continue;
        }
        else if(x=='('){
            s1.push(x);
            continue;
        }
        else if(x==')'){
            while(s1.top()!='('){
                s2.push(s1.top());
                s1.pop();
            }
            if(!s1.empty() && s1.top()=='(')
                s1.pop();
            continue;
        }
        else{
            if(s1.top()=='('){
                s1.push(x);
                continue;
            }
            else{
                while((!compare_precedence(x,s1.top())) && s1.top()!='('){
                    s2.push(s1.top());
                    s1.pop();
                }
                s1.push(x);
                continue;
            }
        }
    }
    if(!s1.empty()){
        while(s1.top()!='#'){
            s2.push(s1.top());
            s1.pop();
        }
    }
    string result;
    for (int index = 0; !s2.empty(); index++){
        result = result + (string(1,s2.top()));
        s2.pop();
    }
    reverse(result.begin(), result.end());
    return result;
}

//比较a的优先级是否大于b,若是则返回true,否则返回false
bool compare_precedence(char a, char b){
    if(b=='#')
        return true;
    else if(a=='*'||a=='/'||a=='%'){
        if(b=='+'||b=='-')
            return true;
        else
            return false;
    }
    else if(a=='+'||a=='-'){
        return false;
    }
    else{printf("Operator compare error!"); return -1;}
}

test:

Example

output

result

((a+b)*c-d)/h+v%e

a+b/c*(d+f)-m

Guess you like

Origin blog.csdn.net/standingflower/article/details/127581291