后缀表达式学习笔记 大佬们的博客 Some Links

版权声明:欢迎大家转载,转载请标明出处。 https://blog.csdn.net/ylsoi/article/details/82800845

中缀表达式:

类似于这样的表达式:a +b * c - ( d * c + e ) / f,就是人类算的表达式,叫做中缀表达式,中缀表达式我们虽然可以轻易地得出运算顺序,但是计算机却不行,需要计算机程序化地处理一个表达式并运算,通常要转化成后缀表达式的形式。

后缀表达式:

上述表达式化为后缀表达式为:a b c * + d c * e + f / -,其运算过程为不断将表达式中的数字压入栈中,如果遇到运算符,则直接将运算符作用于栈最上面的两个元素。
就好像下面这个例子:
8 - ( 3 + 2 * 6 ) / 5 + 4
转化成后缀表达式:
8 3 2 6 * + 5 / - 4 +
8 3 12 + 5 / - 4 +
8 15 5 / - 4 +
8 3 - 4 +
5 4 +
9
这样程序化地计算,则可以在线性时间内得到运算结果。

中缀如何转化成后缀:

由于后缀表达式是按照顺序依次压入栈中并且计算的,所以在转化的时候就应该要考虑各种运算符的运算顺序问题。
这里的处理直接按照顺序读取中缀表达式的每一个部分。
如果中途得到的运算符运算优先级是递增的,那么则不可以立马表示到后缀表达式中,而是要等出现一个运算优先级较底的运算符才可以,这个过程也用栈来处理。
a +b * c,好比这个例子,在+运算符读到的时候+并不是直接作用于a b的,因为后面还有一个优先级较高的运算符*。
于是我们便大体上得到了这样一个流程:

  1. 数字直接放入后缀表达式中。
  2. 如果遇到非括号的运算符,则在放入栈中之前先不断地将优先级级>=此运算符的运算符从栈中弹出并放入后缀表达式。
  3. 遇到左括号,直接放入栈中,不需要弹出任何运算符,因为这括号里面的肯定是要最先算的。遇到左括号,直接放入栈中,不需要弹出任何运算符,因为这括号里面的肯定是要最先算的。
  4. 遇到右括号,表示这个括号里面的东西算完了,相当于结束了一个子算式,直接从栈中弹运算符直到遇到左括号为止。遇到右括号,表示这个括号里面的东西算完了,相当于结束了一个子算式,直接从栈中弹运算符直到遇到左括号为止。

按照上面的步骤进行,中缀就可以转成后缀了。
例题:表达式的转换

#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
typedef long long ll;

using namespace std;

void File(){
    freopen("luogu1175.in","r",stdin);
    freopen("luogu1175.out","w",stdout);
}

const int maxn=1000+10;
int len,tot;
char s[maxn];
stack<char>stk;

int wei(char ch){
    if(ch=='+' || ch=='-')return 1;
    if(ch=='*' || ch=='/')return 2;
    if(ch=='^')return 3;
    return 0;
}

struct node{bool ty;int num;char ch;}qu[maxn];

void popchar(){
    qu[++tot]=(node){1,0,stk.top()};
    stk.pop();
}

void output(int p){
    if(qu[p].ty==0)printf("%d ",qu[p].num);
    else printf("%c ",qu[p].ch);
}
//+ - * / ^ ( will only in the stack

void init(){
    scanf("%s",s+1);
    len=strlen(s+1);
    REP(i,1,len){
        if(isdigit(s[i])){
            qu[++tot]=(node){0,s[i]-'0','\0'};
            continue;
        }
        if(s[i]=='(')stk.push(s[i]);
        else if(s[i]==')'){
            while(stk.top()!='(')popchar();
            stk.pop();
        }
        else{
            while(!stk.empty() && wei(stk.top())>=wei(s[i]))popchar();
            stk.push(s[i]);
        }
    }
    while(!stk.empty())popchar();
    //REP(i,1,tot)output(i);
}

void work(){
    REP(i,1,tot)output(i);
    while(tot>1){
        putchar('\n');
        int p=1;
        while(!qu[p].ty)++p;
        if(qu[p].ch=='+')qu[p-2].num=qu[p-2].num+qu[p-1].num;
        if(qu[p].ch=='-')qu[p-2].num=qu[p-2].num-qu[p-1].num;
        if(qu[p].ch=='*')qu[p-2].num=qu[p-2].num*qu[p-1].num;
        if(qu[p].ch=='/')qu[p-2].num=qu[p-2].num/qu[p-1].num;
        if(qu[p].ch=='^')qu[p-2].num=pow(qu[p-2].num,qu[p-1].num);
        REP(i,p-1,tot-2)swap(qu[i],qu[i+2]);
        tot-=2;
        REP(i,1,tot)output(i);
    }
}

int main(){
//	File();
    init();
    work();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ylsoi/article/details/82800845
今日推荐