码迷,mamicode.com
首页 > 编程语言 > 详细

算法题:四则运算(中缀式到后缀式的转换,值得思考的逆波兰式)

时间:2015-08-03 13:06:59      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:逆波兰式

/*
字符串的四则运算。给出一个字符串,
包含0~9的数字和 + -*\/ ()的运算符,
- 仅代表减号不代表负数。举例如下:
输入:1 + 2 * (3 - 4)
*/



//哈哈,看到这道题,其实一点也不难,这个题根本就不用思考,
//当然是你明白算法之后,这里要用到的算法是逆波兰式。
//如果你有不明白的地方,可以上网搜逆波兰式。

/*
我的总结:计算机无法理解人类的正向思维,于是为了满足计算机的
思维,我们会反其道而行之,将操作符号放在操作数的后面,形成后缀
表达式,但是如果你能按百科上说的思维来做,那么轻而易举的就可以
得到答案。
*/

/*
1.根据表达式构造逆波兰表达式。
2.根据逆波兰表达式进行计算。
3.最终可以轻易的得到结果,我希望大家可以学习一下,共勉。
*/
//Start:

#include <iostream>
#include <string.h>
#include <stack>
using namespace std;

bool Is_Op(char ch)
{
    return (ch == ‘+‘ || ch == ‘-‘ || ch == ‘*‘ || ch == ‘/‘ || ch == ‘(‘ || ch == ‘)‘ || ch == ‘#‘);
}

bool Is_Com(char ch1, char ch2)
{
    //比较符号表达是的优先级。
    int i = 0;
    int j = 0;
    for (; "#+-*/()"[i] != ch1; i++){}
    for (; "#+-*/()"[j] != ch2; j++){}
    bool str[][7] = { 1, 0, 0, 0, 0, 0, 0,
        1, 1, 1, 0, 0, 0, 0,
        1, 1, 1, 0, 0, 0, 0,
        1, 1, 1, 1, 1, 0, 0,
        1, 1, 1, 1, 1, 0, 0,
        1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1 };
    return str[i][j];
}

int  Grial(char *&str)
{
    //先检测括号匹配是否正常吧。
    int flags = 0;
    char *fp = str;
    while (*fp != ‘\0‘)
    {
        if (*fp == ‘(‘)flags++;
        if (*fp == ‘)‘)flags--;
        fp++;
    }
    if (flags != 0)return -1;

    //开始构造波兰表达式。
    strcat(str, "#");
    char *p = str;
    char *q = str;
    stack<char> OP;
    OP.push(‘#‘);
    stack<string>  NM;
    int count = 0;
    string s;
    while (*p != ‘\0‘)
    {
        if (Is_Op(*p))
        {
            if (*p == ‘)‘)
            {
                while (OP.top() != ‘(‘)
                {
                    s = OP.top();
                    NM.push(s);
                    OP.pop();
                }
                if (OP.top() == ‘(‘)
                {
                    OP.pop();
                    p++;
                    continue;
                }
            }
            if (Is_Com(OP.top(), *p) && OP.top() != ‘(‘)
            {
                while (Is_Com(OP.top(), *p))
                {
                    s = OP.top();
                    NM.push(s);
                    OP.pop();
                    if (*p == ‘#‘ && OP.top() == ‘#‘)break;
                }
                OP.push(*p);
            }
            else
            {
                OP.push(*p);
            }
            p++;
        }
        else
        {
            while (!Is_Op(*p))
            {
                count = count * 10 + *p - ‘0‘;
                p++;
                if (*p == ‘\0‘ || *p == ‘#‘)break;
            }

            char buff[255];
            memset(buff, 0, sizeof(buff));
            itoa(count, buff, 10);
            s = buff;
            NM.push(s);
            count = 0;
        }
    }
    stack<string> numSt;

    while (NM.empty() == false)
    {
        numSt.push(NM.top());//逆序。
        NM.pop();
    }
    //目前为止已经构造好了逆波兰式,下面让我们来计算吧。

    stack<int> temp;
    while (numSt.empty() == false)
    {
        if (numSt.top() == "+" || numSt.top() == "-" || numSt.top() == "*" || numSt.top() == "/")
        {
            int a = temp.top();
            temp.pop();
            int b = temp.top();
            temp.pop();
            if (numSt.top() == "+")
            {
                temp.push(b + a);
            }
            else if (numSt.top() == "-")
            {
                temp.push(b - a);
            }
            else if (numSt.top() == "*")
            {
                temp.push(b*a);
            }
            else if (numSt.top() == "/")
            {
                temp.push(b / a);
            }
            numSt.pop();
        }
        else
        {
            temp.push(atoi(numSt.top().c_str()));
            numSt.pop();
        }
    }
    return temp.top();
}

int main()
{
    ;
    char *s = new char[20];
    memset(s, 0, sizeof(s));

    strcpy(s, "(1+2)*3-(1+2)/4+10");
    cout << Grial(s) << endl;

    strcpy(s, "1+2+4+(1*2)/3+4");
    cout << Grial(s) << endl;

    strcpy(s, "3+(4/2)+1+2-1*2");
    cout << Grial(s) << endl;

    strcpy(s, "(1+(2+3)*4)+2-0");
    //我还担心自己的双重括号没有考虑到,
    //没想到一次成功。
    cout << Grial(s) << endl;
    return 0;
}

技术分享

版权声明:本文为博主原创文章,未经博主允许不得转载。

算法题:四则运算(中缀式到后缀式的转换,值得思考的逆波兰式)

标签:逆波兰式

原文地址:http://blog.csdn.net/liuhuiyan_2014/article/details/47254491

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!