Fork me on GitHub

数据结构——栈——中缀表达式和后缀表达式

什么是中缀表达式,什么是后缀表达式

我们一般看见的多项式计算都是中缀表达式构成的:1+2*3+4/3

类似这种,为什么说是中缀呢?因为它的计算符号都是在两个数中间的。

那么自然而然的明白了后缀表达式是一种计算符号在两个数后面的。

如123*+43/+

 

中缀表达式和后缀表达式有什么关系?

其实仔细你就会发现,上面给出的式子其实都是一样的,只是计算的顺序在后缀表达式中你看不懂而已。

因为我们习惯去看中缀表达式的计算。

其实他们之间是可以互相转换的。他们也可以表达同一个意思,同一个计算式子。

 

为什么会提出后缀表达式

这里马上就会有问题了,为什么好好的不用中缀表达式,而提出那么一个难看的后缀表达式。

首先对于我们人来说,计算的时候看到乘法和除法自然而然的就会去先计算,而对于计算机这么笨的东西来说,它不知道。

对于中缀表达式来说,计算机不能预料到后面是否会出现高阶的计算符号,是否要先进行计算,所以在计算的次序上面很有可能出错。

所以就有了后缀表达式,计算机在计算后缀表达式的时候不用担心计算的次序。那么问题就来了,如何计算一个后缀表达式的值呢?

别急,我们先来看看如何把一个中缀表达式转换成一个后缀表达式。

 

中缀表达式转换成后缀表达式

这里我们提前约定一下,我们的式子包含加减乘除和小括号,所有的数据我们暂时用个位数来表示,不包含次方开方和中括号。当然也不是可以,我们这边将问题尽量简单化。

1.   从左向右扫遍历表达式:
2.   If 当前遍历到的字符 ch 是操作数,则打印
3.   Else If 当前遍历的ch是 ‘(‘, 入栈
4.   Else If 当前遍历的ch是 ‘)’, 不断弹出栈顶元素,直到栈为空或弹出’(‘
5.   Else,
…….5.1 If  上一个操作符的优先级比当前操作符ch的优先级小,或栈是空的就入栈。
……. 5.2 Else, 不断弹出栈顶的操作符,并打印,直到栈为空或当前的操作符ch的优先级大于栈顶的操作符。将当前操作符入栈。
6.  重复2-6步,直到遍历完成
7.  弹出并打印栈中的剩余的操作符

 

代码描述

#include<cstdio> 
#include<iostream>
#include<cstdlib>
#include<string> 
#include<string.h> 
#include<stack>

using namespace std;

int getRank(char sign)
{
    switch(sign)
    {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
    }
    return -1;
}

int main()
{
    int i=0;
    stack<char> expStack;
    string expression;
    cin>>expression;
    
    for(i=0; i<expression.length(); i++)
    {
        if(expression[i]>='0' && expression[i]<='9')
        {
            cout<<expression[i];
        }
        else if(expression[i] == '(')
        {
            expStack.push(expression[i]);
        }
        else if(expression[i] == ')')
        {
            char top = expStack.top();
            expStack.pop();
            while(!expStack.empty() && top != '(')
            {
                cout<<top;
                top = expStack.top();
                expStack.pop();
            }
        }
        else
        {
            int now = getRank(expression[i]);
            if(expStack.empty() || now > getRank(expStack.top()))
            {
                expStack.push(expression[i]);
            }
            else
            {
                while(!expStack.empty() && now <= getRank(expStack.top()))
                {
                    cout<<expStack.top();
                    expStack.pop();
                }
                expStack.push(expression[i]);
            }
        }
    }
    
    while(!expStack.empty())
    {
        cout<<expStack.top();
        expStack.pop();
    }
    return 0;
}

 

 

后缀表达式的计算

我们现在已经能得到后缀表达式了,那么如何利用它计算。

其实很简单,首先我们观察到后缀表达式中已经没有任何括号了,所以对于我们来说计算顺序就很容易了。

从左往右读取,数字入栈,如果遇到计算符号(比如遇到一个加号),出栈两个数然后计算(比如两个数相加),然后将结果入栈。

最后在栈中的数据就为计算的结果。

 

思考

栈对于带有括号的计算式,四则运算等比较好用,利用栈的特性能保存一些计算等级低的,让等级高的先进行计算。

之后遇到这样的问题可以首先考虑使用栈。

posted @ 2016-12-18 23:30  LinkinStar  阅读(3695)  评论(0编辑  收藏  举报