Postfix infix expression turn learning record

I do not know what that something is something

background

Want to do Los Valley P1054 , thought can bring in the case of the same model number prime number count value comparison, but I do not how to bring value, the"B station"On a search method can be used infix expression turn suffix table, after learning with this note.

A chestnut

First of all, we give a chestnut infix expression (the chestnuts should be very full, and basically includes all symbols (except "^", "%") and priority adjustments, if incomplete please ask, I'll try to completion) : + $ 9 (9 + 8/6 + 4-9) 8-7 + ((2 + 3) 3) $(For the primary school is the root of all evil four operations)

Suffix and its expression is: $ 9984 / + 9--6 + 8 * + 7--23 + $ + 3 *

The concept postfix expression

The concept on Wikipedia

Reverse Polish Notation (Reverse Polish notation, RPN, or reverse Polish notation), is a mathematical expression by way Polish mathematician Jan Łukasiewicz in 1920 introduced reverse Polish notation, all operations, symbol placed behind the operands, is also known as postfix notation. Reverse Polish notation parentheses are not required to identify the priority level of the operator.

The concept of a degree

Postfix notation, also known as inverse Polish, referring not contain brackets, operators on two operands later, all calculations in order operators appear, strictly from left to right (no longer consider operation operator precedence rules).

Do not understand, do not understand it, anyway, after I learned not understand, only know ye use. . .

Positive: postfix infix expression turn

The concept && method

1, by any operand infix expressions, operators, parentheses, these three parts.

2, which decorated expression on the left to start scanning, if the encounter operands directly outputs (not pushed onto the stack).

3. If you encounter a left parenthesis, it is pushed onto the stack.

4. If you encounter a right parenthesis, expression infix expression in parentheses has been scanned. The time required to stack and pop operators are sequentially output, until it encounters the left bracket [left bracket but do not pop out].

5, if the operator is encountered: a, if the operator priority higher than the priority of the operator stack, push it

B, if the operator priority is less than the priority of the operator stack, the top of the stack and pop operators output, and then comparing the new top of stack operator, if it exceeds, it is pushed onto the stack, if less than, operators continue to be top of the stack is popped and the output ...... (recursion has been, until the operator until the operator is greater than the top of the stack).

6, the last step of the scanning to the end of infix expressions [i.e. End Scan], the stack if there are remaining operators can be sequentially ejected and output.

Manual simulation

Read the above methods should be a lot of people are ignorant of,me tooSo I try to look for a simulation.

But ......

I checked for a long time to no avail special all-analog, so clothed yourself, I hand made a comparison of the whole, which is in front of chestnuts (of course, not a member of "^", "%", so be it temporarilyBecause I still do not understand the priority of these two things ...)

Scan to the elements $ S2 $ (bottom of the stack -> stack) $ $ Sl (bottom of the stack -> stack) Explanation
$9$ $9$ air Digital, direct push
$+$ $9$ $+$ $ S1 $ empty directly onto the stack
$($ $9$ $+ ($ Left parenthesis, direct push
$9$ $9 9$ $+ ($ Digital, direct push
$+$ $9 9$ $+ ( +$ $ S1 $ stack is a left parenthesis, direct push
$8$ $9 9 8$ $+ ( +$ Digital, direct push
$/$ $9 9 8$ $+ ( + /$ Sl stack is $ $ "$ + $", priority is lower than "$ / $" Direct Drawing
$4$ $9 9 8 4$ $+ ( + /$ Digital, direct push
$-$ $9 9 8 4 / +$ $+ ( -$ Sl stack of $ $ "$ / $", the priority level is greater than "$ - $" $ S2 $ pop to the left bracket (ratio "$ / $" higher priority first operator) and pushed into "$ - $"
$9$ $9 9 8 4 /+9$ $+ ( -$ Digital, direct push
$+$ $9 9 8 4 /+9 -$ $+ ( +$ Sl stack is $ $ "$ - $", "$ + $" priority is equal to "$ - $" $ S2 $ pop to the left bracket (ratio "$ - $" first operand greater priority Fu) and pressed into the "$ + $"
$6$ $9 9 8 4 /+9-6$ $+ ( +$ Digital, direct push
$)$ $9 9 8 4 /+9-6 +$ $+$ Right parenthesis, the $ S2 $ pop to left parenthesis
$*$ $9 9 8 4 /+9-6 +$ $+ *$ Sl stack is $ $ "$ + $", priority is lower than "$ * $" Direct Drawing
$8$ $9 9 8 4 /+9-6 +8$ $+ *$ Digital, direct push
$-$ $9 9 8 4 /+9-6 +8*+$ $-$ Sl stack is $ $ "$ $", the priority level is greater than "$ - $", than to pop "$ $" higher priority first operator (i.e. of stack) and pressed into the "$ - $"
$7$ $9 9 8 4 /+9-6 +8*+7$ $-$ Digital, direct push
$+$ $9 9 8 4 /+9-6 +8*+ 7 -$ $+$ Sl stack is $ $ "$ - $", "$ + $" priority is equal to "$ - $", the pop-up to the ratio "$ - $" greater priority first operator (i.e., the end of the stack) and pushed "$ + $"
$($ $9 9 8 4 /+9-6 +8*+ 7 -$ $+ ($ Left parenthesis, direct push
$($ $9 9 8 4 /+9-6 +8*+ 7 -$ $+ ( ($ Left parenthesis, direct push
$2$ $9 9 8 4 /+9-6 +8*+ 7-2$ $+ ( ($ Digital, direct push
$+$ $9 9 8 4 /+9-6 +8*+ 7-2$ $+ ( ( +$ $ S1 $ stack is a left parenthesis, direct push
$3$ $9 9 8 4 /+9-6 +8*+ 7-2 3$ $+ ( ( +$ Digital, direct push
$)$ $9 9 8 4 /+9-6 +8*+ 7-2 3 +$ $+ ($ Right parenthesis, the $ S2 $ pop to left parenthesis
$*$ $9 9 8 4 /+9-6 +8*+ 7-2 3 +$ $+ ( *$ $ S1 $ stack is a left parenthesis, direct push
$3$ $9 9 8 4 /+9-6 +8*+ 7-2 3+3$ $+ ( *$ Digital, direct push
$)$ $9 9 8 4 /+9-6 +8+ 7-2 3+3 $ $+$ Right parenthesis, the $ S2 $ pop to left parenthesis
Reach rightmost $9 9 8 4 /+9-6 +8+ 7-2 3+3+$ air $ $ Sl eject all remaining operators

So we can be simulated by the analog conjugated table S1, S2 -> suffix process.

Code

#include<bits/stdc++.h>
using namespace std;
 
map<char,int> p;
 
struct Node
{
    double num;//操作数
    char op;//操作符
    bool flag;//true表示操作数,false表示操作符
};
typedef struct Node node;
 
stack<node> s1;//操作符栈(意义同表)
queue<node> s2;//后缀表达式队列(意义同表)

void change(string str)
{
    node temp;
    for (int i = 0; i < str.length();)
    {
         if (str[i] == '(')//3.遇到左括号:将其压栈
         {
            temp.flag = false;
            temp.op = str[i];
            s1.push(temp);
            i++;
        }
        else if (str[i] == ')')//4.遇到右括号:执行出栈操作,输出到后缀表达式,直到弹出的是左括号
        {
            while (!s1.empty() && s1.top().op != '(')
            {
                s2.push(s1.top());
                s1.pop();
            }
            s1.pop();//弹出左括号**一定要注意将左括号弹出去,否则后面如果有右括号就jj了**
            i++;
        }
        else if (isdigit(str[i]))
        {
            //如果是数字
            temp.flag = true;
            temp.num = str[i] - '0';
            i++;//后移一位,因为数字不一定是个位数
            while (i < str.length() && isdigit(str[i]))
            {
                temp.num = temp.num * 10 + (str[i] - '0');
                i++;
            }
            s2.push(temp);//操作数进入后缀表达式
        }
        else
        {
            //如果是操作符(如果处理空格可加入另一个else if,在此懒得写owo)
            //5.遇到其他运算符:弹出所有优先加大于或等于该运算符的栈顶元素,然后将该运算符入栈
            temp.flag = false;
            while (!s1.empty() && p[s1.top().op]>=p[str[i]])
            {
                s2.push(s1.top());
                s1.pop();
            }
            temp.op = str[i];
            s1.push(temp);
            i++;
        }
    }
    //6.将栈中剩余内容依次弹出后缀表达式
    while (!s1.empty())
    {
        s2.push(s1.top());
        s1.pop();
    }
}
int main()
{   
    node now;
    string str;
    p['+'] = p['-'] = 1;//给予优先级
    p['*'] = p['/'] = 2;//给予优先级
    cin >> str;
    change(str);
    while (!s2.empty()){
        now = s2.front();
        if (now.flag == true) cout << now.num<<" "; 
        else cout << now.op<<" ";   
        s2.pop();
    }
 
    return 0;
}

I believe that if the previous explanations carefully read, then this code should be understood got up.

Postscript: calculated values

Why is there this thing

​ 既然已经有这个东西,那么不计算要它有个什么用。所以顺便把计算也学了

那么计算的过程

​ 1.从左到右扫描后缀表达式

​ 2.如果是数,压栈

​ 3.如果是符号,将弹出两个操作数,进行计算,计算的结果再压入栈中

最后栈顶的元素就是所要的值

也许。。。(只是也许!敲黑板!)你不明白这三个是什么东西,所以还是模拟一下

手动模拟

扫描到的元素 s3 说明
$9$ $9$ 数字,压栈
$9$ $9 9$ 数字,压栈
$8$ $9 9 8$ 数字,压栈
$4$ $9 9 8 4$ 数字,压栈
$/$ $9 9 2$ 符号,将"$4$"、"$8$"弹出,计算"$8/4$",得到"$2$",压栈
$+$ $9 11$ 符号,将"$2$"、"$9$"弹出,计算"$9+2$",得到"$11$",压栈
$9$ $9 11 9$ 数字,压栈
$-$ $9 2$ 符号,将"$9$"、"$11$"弹出,计算"$11-9$",得到"$2$",压栈
$6$ $9 2 6$ 数字,压栈
$+$ $9 8$ 符号,将"$6$"、"$2$"弹出,计算"$2+6$",得到"$8$",压栈
$8$ $9 8 8$ 数字,压栈
$*$ $9 64$ 符号,将"$8$"、"$8$"弹出,计算"$8*8$",得到"$64$",压栈
$+$ $73$ 符号,将"$64$"、"$9$"弹出,计算"$9+64$",得到"$73$",压栈
$7$ $73 7$ 数字,压栈
$-$ $66$ 符号,将"$7$"、"$73$"弹出,计算"$73-7$",得到"$66$",压栈
$2$ $66 2$ 数字,压栈
$3$ $66 2 3$ 数字,压栈
$+$ $66 5$ 符号,将"$3$"、"$2$"弹出,计算"$2+3$",得到"$5$",压栈
$3$ $66 5 3$ 数字,压栈
$*$ $66 15$ 符号,将"$3$"、"$5$"弹出,计算"$5*3$",得到"$15$",压栈
$+$ $81$ 符号,将"$15$"、"$66$"弹出,计算"$66+15$",得到"$81$",压栈
到达最右端 将$81$弹出,作为结果输出

贴份代码


#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
using namespace std;

map<char, int> p;

struct Node
{
    double num;//操作数
    char op;//操作符
    bool flag;//true表示操作数,false表示操作符
};
typedef struct Node node;
 
stack<node> s1;//操作符栈
queue<node> s2;//后缀表达式队列
stack<node> s3;//存放操作数的,为了计算后缀表达式的值

void change(string str)
{
    node temp;
    for (int i = 0; i < str.length();)
    {
        if (str[i] == '(')//3.遇到左括号:将其压栈
        {
            temp.flag = false;
            temp.op = str[i];
            s1.push(temp);
            i++;
        }
        else if (str[i] == ')')//4.遇到右括号:执行出栈操作,输出到后缀表达式,直到弹出的是左括号
        {
            while (!s1.empty() && s1.top().op != '(')
            {
                s2.push(s1.top());
                s1.pop();
            }
            s1.pop();//弹出左括号**一定要注意将左括号弹出去,否则后面如果有右括号就jj了**
            i++;
        }
        else if (isdigit(str[i]))
        {
            //如果是数字
            temp.flag = true;
            temp.num = str[i] - '0';
            i++;//后移一位,因为数字不一定是个位数
            while (i < str.length() && isdigit(str[i]))
            {
                temp.num = temp.num * 10 + (str[i] - '0');
                i++;
            }
            s2.push(temp);//操作数进入后缀表达式
        }
        else
        {
            //如果是操作符(如果处理空格可加入另一个else if,在此懒得写owo)
            //5.遇到其他运算符:弹出所有优先加大于或等于该运算符的栈顶元素,然后将该运算符入栈
            temp.flag = false;
            while (!s1.empty() && p[s1.top().op]>=p[str[i]])
            {
                s2.push(s1.top());
                s1.pop();
            }
            temp.op = str[i];
            s1.push(temp);
            i++;
        }
    }
    //6.将栈中剩余内容依次弹出后缀表达式
    while (!s1.empty())
    {
        s2.push(s1.top());
        s1.pop();
    }
}

double  calculate()
{
    double tmpa, tmpb;//临时的a、b(在计算的时候用到)
    node tmp, temp;
    while (!s2.empty())
    {//后缀队列非空
        tmp = s2.front();//记录队首元素
        s2.pop();
        if (tmp.flag == true)
        {//是数就压栈
            s3.push(tmp);
        }
        else
        {//是符号就运算
            tmpb = s3.top().num;
            s3.pop();//弹出第二个数(众所周知,先入后出)
            tmpa = s3.top().num;
            s3.pop();//弹出第一个数
            temp.flag = true;
            if (tmp.op == '+')
                temp.num = tmpa + tmpb;
            else if (tmp.op == '-')
                temp.num = tmpa - tmpb;
            else if (tmp.op == '*')
                temp.num = tmpa * tmpb;
            else
                temp.num = tmpa / tmpb;
            s3.push(temp);//把计算后的结果再次压栈
        }
    }
    return s3.top().num;
 
}

int main()
{
    string str;
    node now;
    p['+'] = p['-'] = 1;
    p['*'] = p['/'] = 2;
    cin >> str;
    change(str);
    // while (!s2.empty())
    // {
    //  now = s2.front();
    //  if (now.flag == true) cout << now.num << " ";
    //  else cout << now.op << " ";
    //  s2.pop();
    // }//之前输出后缀的函数
    while (!s3.empty())
    {
        s3.pop();
    }
    double answer=calculate();
    cout << answer << endl;
    return 0;
}

好了,希望能明白,第一次写学习笔记,有不足之处请多指教啦owo

Guess you like

Origin www.cnblogs.com/fkx4-p/p/11302568.html