zoukankan      html  css  js  c++  java
  • [经典算法]后序式的运算

    题目说明:

    通过将中序式转换为后序式,不用处理运算子先后顺序问题,只要依序由运算式由前往后读取即可。

    题目解析:

    运算时由后序式的前方开始读取,遇到运算元先存入堆叠,如果遇到运算子,则由堆叠中取出两个运算元进行对应的运算,然后将结果存回堆叠,如果运算式读取完 毕,那么堆叠顶的值就是答案了,例如我们计算12+34+*这个运算式(也就是(1+2)*(3+4)):

    读取

    堆叠

    1

    1

    2

    1 2

    +

    3 // 1+2 后存回

    3

    3 3

    4

    3 3 4

    +

    3 7 // 3+4 后存回

    *

    21 // 3 * 7 后存回

    程序代码:

    #include <gtest/gtest.h>
    
    using namespace std;
    
    int GetOperatorPrior(char value)
    {
        int nResult = 0;
        switch(value)
        {
        case '+':
        case '-':
            {
                nResult = 1;
            }
            break;
    
        case '*':
        case '/':
            {
                nResult = 2;
            }
            break;
        }
    
        return nResult;
    }
    
    bool ConvertToPostfix(const string& infixExp, string& postfixExp)
    {
        postfixExp.clear();
        int* pStack = new int[infixExp.size()];
        int nTop = -1;
    
        for (string::size_type i=0; i < infixExp.size(); i++)
        {
            char cValue = infixExp[i];
            switch (cValue)
            {
            case '(':
                {
                    pStack[++nTop] = cValue;
                }
                break;
    
            case ')':
                {
                    while ( (nTop >= 0) && pStack[nTop] != '(')
                    {
                        postfixExp += pStack[nTop];
                        --nTop;
                    }
                    // not find '(', express is invalid.
                    if (nTop < 0)
                    {
                        return false;
                    }
    
                    --nTop;
                }
                break;
    
            case '+':
            case '-':
            case '*':
            case '/':
                {
                    while ( (nTop >= 0) &&
                        GetOperatorPrior(pStack[nTop]) >= GetOperatorPrior(cValue))
                    {
                        postfixExp += pStack[nTop];
                        --nTop;
                    }
    
                    pStack[++nTop] = cValue;
                }
                break;
    
            default:
                postfixExp += cValue;
                break;
            }
        }
    
        while (nTop >= 0)
        {
            postfixExp += pStack[nTop--];
        }
    
        return true;
    }
    
    bool CalcValue(double v1, double v2, double& value, char express)
    {    
        bool bResult = true;
        switch (express)
        {
        case '+':
            value = v1 + v2;        
            break;
    
        case '-':
            value = v1 - v2;
            break;
    
        case '*':
            value = v1 * v2;
            break;
    
        case '/':
            if (fabs(v2) < 1e-15)
            {
                return false;
            }
    
            value = v1 / v2;
            break;
    
        default:
            bResult = false;
            break;
        }
    
        return bResult;
    }
    
    bool ExpressCalc(const string& express, double& value)
    {
        string PostfixExpress;
        if (!ConvertToPostfix(express, PostfixExpress))
        {
            return false;
        }
    
        double* OperandStack = new double[PostfixExpress.size()];
        int nTop = -1;
    
        for (string::size_type i = 0; i < PostfixExpress.size(); ++i)
        {
            char cValue = PostfixExpress[i];
            switch (cValue)
            {
            case '+':            
            case '-':
            case '*':
            case '/':
                {
                    // Operand not enough
                    if (nTop < 1)
                    {
                        return false;
                    }
    
                    double dResult;
                    if (!CalcValue(OperandStack[nTop-1], OperandStack[nTop], dResult, cValue))
                    {
                        return false;
                    }
    
                    OperandStack[nTop-1] = dResult;
                    --nTop;
                }
                break;
    
            default:
                if (cValue < '0' && cValue > '9')
                {
                    return false;    
                }
                OperandStack[++nTop] = cValue - '0';
    
                break;
            }
        }
    
        if (nTop >= 1)
        {
            return false;
        }
    
        value = OperandStack[0];
    
        return true;
    }
    
    TEST(Algo, tExpressCalc)
    {
        //
        //    Postfix Convert
        //
    
        // a+b*d+c/d => abd*+cd/+
        string strResult;
        ConvertToPostfix("a+b*d+c/d",strResult);
        ASSERT_EQ("abd*+cd/+",strResult);
    
        // (a+b)*c/d+e => ab+c*d/e+
        ConvertToPostfix("(a+b)*c/d+e",strResult);
        ASSERT_EQ("ab+c*d/e+",strResult);
    
        // ((a)+b*(c-d)+e/f)*g => abcd-*+ef/g*
        ConvertToPostfix("((a)+b*(c-d)+e/f)*g",strResult);
        ASSERT_EQ("abcd-*+ef/+g*",strResult);
    
        // 1+3*4+2/5 => 13.4
        double dResult = 0.0;
        ExpressCalc("1+3*4+2/5",dResult);
        ASSERT_DOUBLE_EQ(13.4,dResult);
    
        // (4+6)*1/9+7 => 8.1111111111111111111111111111111
        ExpressCalc("(4+6)*1/9+7",dResult);
        ASSERT_DOUBLE_EQ(8.1111111111111111111111111111111,dResult);
    
        // ((5)+2*(1-7)+3/8)*4 => -26.5
        ExpressCalc("((5)+2*(1-7)+3/8)*4",dResult);
        ASSERT_DOUBLE_EQ(-26.5,dResult);
    }
  • 相关阅读:
    Sql server 2005 restore failed
    使用Windows Live Writer发布到cnblogs
    IE7 Tab problem
    转: 编码,charset,乱码,unicode,utf8与net简单释义(续)
    移动12.1号动感地带寻宝答案
    转: 各种 lightbox 实现
    Cannot connect windows 2003 server remotely by mstsc
    boost asio 网络编程案例简单改写
    读书笔记之《程序员的自我修养链接、装载与库》
    基于OpenSSL简单实现Shamir基于身份的数字签名算法
  • 原文地址:https://www.cnblogs.com/Quincy/p/4829334.html
Copyright © 2011-2022 走看看