zoukankan      html  css  js  c++  java
  • 数据结构——栈——中缀表达式和后缀表达式

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

    我们一般看见的多项式计算都是中缀表达式构成的: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;
    }

     

    后缀表达式的计算

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

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

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

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

    思考

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

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

  • 相关阅读:
    Qt QString判断是否是数字
    Qt 判断QString中的字符串是否为纯数字
    Qt delete和deletelater的区别
    Qt QTcpSocket waitForReadyRead()等函数用法——客户端开关读写应用笔记
    Notepad++对比两个文件不同的方法
    Qt error C1071 :在注释中遇到意外的文件结束
    Qt error C2601: “...”: 本地函数定义是非法的
    Qt 错误 C1071 在注释中遇到意外的文件结束 的解决办法
    Qt 串口和线程的简单结合(通过子线程操作串口、movetothread)
    Qt 实现多线程的串口通信
  • 原文地址:https://www.cnblogs.com/linkstar/p/6195993.html
Copyright © 2011-2022 走看看