Infix expression evaluation (application of stack)

Topic:
Expression evaluation

Question meaning:
Given a length not exceeding 1 0 5 10^510The expression of 5 , please find the value of this expression.
Ensure that the digital calculation process will not be directly obtained digital negative, and only+,-,*,/,(,)this666 kinds of characters.
Data range:∣ s ∣ ≤ 1 0 5 |s| \leq 10^5s105

Solution:
Here we call addition and subtraction add, and multiplication and division mul.
Because subtraction can be converted to a number plus a negative number, the denominator of division can be converted to an inverse element under the modulus of the denominator.

Consider that we usually evaluate an infix expression without parentheses . There are about four situations as follows:

  • Before addafter add: a+b+dthen we can first calculated a+b=c, and then calculate c+dcan.
  • Before mulafter mul: a*b*dthen we can first calculated a*b=c, and then calculate c*dcan.
  • Before mulafter add: a*b+dthen we can first calculated a*b=c, and then calculate c+dcan.
  • Before addlater mul: a+b*dthis time due to the higher number take priority, we need to obtain the result of the multiplication b*d=c, and then calculate a+c.

You can see the first three cases. When the 前一个计算符号priority is not 后一个计算符号lower than the priority, it can be calculated directly, and then the calculation result is substituted into the subsequent expression for calculation. When the 前一个计算符号priority is lower than the 后一个计算符号priority, it can only wait for 后一个计算符号the calculation result and then perform the calculation.
In summary, we can consider maintaining a monotonic stack with strictly monotonically increasing symbol priority. It can be imagined that this stack will not use much memory, because there will only be two elements in the stack at most, and the bottom of the stack is a plus or minus sign. The top is a multiplication sign or a division sign.


Next consider the calculation with brackets.
Brackets are symbols to increase the precedence of an expression, but do not perform actual addition, subtraction, multiplication, and division calculations.
Corresponding to about three infix expressions:

  • Before add/mulafter (): a*(b+c)etc ...
    This calculation expression of the previous addpost mulis the same, but we need to calculate the value of the expression in parentheses. So in any case, it (must be able to be pushed into the stack, and the calculations in the stack are the same as ordinary calculations.

  • Before (after ): (a+b)and so on ...
    In fact, this is the expression in parentheses is evaluated, when we encounter a )time, indicating that ), and it matches the (expression between the brackets for the corresponding bracket expression, at this time indicates that the brackets The expression needs to be calculated to get the calculation result.
    It should be noted that, due to the opening parenthesis can stack in any case, so when encountered ((a+b))or (a+(b*c+d))when such a case, the stack after stack will no longer meet the strict monotonically increasing stack attributes, so here is monotonous stack The nature of strictly monotonically increasing will be no longer complete due to the existence of the left parenthesis, but every two left parentheses as a delimiter of the calculation symbol sequence will individually meet the strict monotonic increase. Of course, the length of these symbol sequences will not be greater than twenty two2 .
    As(the stack, any sign of the expression can be pushed onto the stack, it said its priority is reduced to a minimum.
    We can add one(at the beginning andoneat the end ofa given expression to)ensure the integrity of the overall description and at the same time make the calculation need not be solved separately. Specificallya+b, you need to operate the stack separately after the stack is built. Adding a parenthesis at the beginning and the end will make the implementation more beautiful.

  • Before ()after add/mul: (a+b)*cThis op mulafter addcalculation, will not repeat them.


This question has explained that there will be no negative numbers, but there are still ways to distinguish the two types of specific negative numbers and minus signs.
Consider when it -will act as a minus sign:

  • When the -front is )when
  • When -the front is a number

Both of these indicate that the -previous expression can be directly calculated as the calculation of the expression after the result is substituted, which is determined by the priority of the minus sign being the lowest in the calculation symbol.

Code:
This code supports 2 31 − 1 2^{31}-1231Add, subtract, multiply and divide with negative numbers within 1 and calculate in parentheses.

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1e5 + 10;
char op[N]; int topo;
int num[N]; int topn;
char s[N];
int n;

int cal(char ch) {
    
    
    int b = num[topn--];
    int a = num[topn--];
    if(ch == '+') return a + b;
    else if(ch == '-') return a - b;
    else if(ch == '*') return a * b;
    return a / b;
}

int level(char ch) {
    
    
    if(ch == '(') return 0;
    else if(ch == '+' || ch == '-') return 1;
    return 2;
}

bool check_f(int i) {
    
    
    if(i > 2 && (isdigit(s[i - 1]) || s[i - 1] == ')')) return false;
    return true;
}

int main()
{
    
    
    scanf("%s", s + 2);
    n = strlen(s + 2) + 2;
    s[1] = '(', s[n] = ')';
    for(int i = 1; i <= n; ++i) {
    
    
        if(isdigit(s[i]) || (s[i] == '-' && check_f(i))) {
    
    
            int c = 0, f = 1;
            if(s[i] == '-') f = -1, ++i;
            while(i <= n && isdigit(s[i])) c = c * 10 + s[i] - '0', ++i;
            num[++topn] = c * f;
            --i;
        }
        else {
    
    
            if(s[i] == '(') op[++topo] = s[i];
            else if(s[i] == ')') {
    
    
                while(topo > 0 && op[topo] != '(') {
    
    
                    char ch = op[topo--];
                    int c = cal(ch);
                    num[++topn] = c;
                }
                --topo;
            }
            else {
    
    
                while(topo > 0 && op[topo] != '(' && level(s[i]) <= level(op[topo])) {
    
    
                    char ch = op[topo--];
                    int c = cal(ch);
                    num[++topn] = c;
                }
                op[++topo] = s[i];
            }
        }
    }
    
    printf("%d\n", num[topn]);
    
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43900869/article/details/114809135