• 简单计算机——逆波兰表达式


    逆波兰数:逆波兰数由两部分组成(操作数,操作符)——是波兰表达式的一种,即操作符在操作数的后面。

    形式:A+B*C-D = ABC*D-;

       (A+B)*C-D = AB+C*D-;

    既然我们知道了,后缀表达式那我们表达式是唯一的吗?我们来看一组数据:

    例如:(A+B)*C-D 和 C*(A+B)-D;

    很显然第二个的表达式为:C*AB+D-;虽然对最后的结果无影响,但我们需要知道逆波兰的多样性。

    注意事项:

    1、如果出现1+23 = 123+,该如何判断它的数值呢?

      可以利用分割符来进行很好的辅助性理解,例如1+23 = 1#23#+,这样可以完美的解决此问题。

    2、存在括号的时候该如何处理?

      其一:是‘(’直接压入,‘)’时,将两者之间的运算符弹出,压入后缀表达式。

      其二:遇到‘(’开辟一个新的运算符栈,‘)’时,当前栈内运算符弹出,压入后缀表达式。

    算法:

    1、中缀表达式——逆波兰表达式的转变。

    • 准备一个栈一个链表,链表用来存操作数,栈用来存操作符。
    • 如果为操作数,我们继续判断它的下一位是否也为操作数,是——则继续压入,否——压入分隔符(“#”)。同时判断字符栈中,是否为“*”,“/”,字符弹出,压入数值链表。
    • 如果为操作符,直接压入字符栈。
    • 如果‘(’,重新开辟一个新字符栈,其它操作相同。
    • 如果‘ )’,将当前字符栈内部的字符逐个弹出,压入数值链表。

    2、逆波兰求值。

    • 准备一个栈,用来逐个求当前值。
    • 依次取出数值链表的第一个值。
    • 根据加减乘除运算做出相应的操作,即取出当前栈的前两个值,做运算符操作。
    • 如果是操作数,我们继续判断它的下一位是否也为操作数,是——n*10+char-‘0’,否——压入栈中;
    • 最后的到栈顶元素,即为运算后的值。

    核心代码:

    1、中缀表达式——逆波兰表达式的转变。

    bool is_char(char c)//判断是否为操作符
    {
        return c == '-' || c == '+' || c == '*' || c == '/';
    }
    
    void change()//表达式的转化
    {
        char c;
        int i = 0, j = 0;//i遍历输入的字符,j不同层数的字符栈
        while ((c = original[i++]) != '')
        {
            if (is_char(c))//是字符
                one[j].push(c);
            else if (is_number(c))//是数字
            {
                int x = i;//
                while (is_number(c))
                {
                    sconed.push_back(c);
                    if (is_number(c = original[x++]))//是数值,则数组往后移动一位(确保下一步能读取字符)
                        i++;
                }
                sconed.push_back('#');//分隔符
                if (!one[j].empty())//判断是否为空
                    if (one[j].top() == '*' || one[j].top() == '/')//高阶运算,直接取出,压入数值链表
                    {
                        sconed.push_back(one[j].top());
                        one[j].pop();
                    }
            }
            else if (c == ')')
            {
                Dum(j);//多余的运算符赋值
                j--;//回到上一层的字符栈
            }
            else
                j++;//新的字符栈
        }
        Dum(j);
    }
    
    void Dum(int j)//多余的运算符逐个压入数值链表
    {
        while (!one[j].empty())
        {
            sconed.push_back(one[j].top());
            one[j].pop();
        }
    }
    View Code

    2逆波兰求值。

    void Do_it(std::stack<int> &mc)
    {
        while (!sconed.empty())//不为空时。
        {
            char mid = sconed.front();//临时存储字符
            sconed.pop_front();//压出
            switch (mid)//判断
            {
                int a, b;
            case'-':
                b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行减法运算。
                mc.push(a - b);
                break;
            case'+':
                b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行加法运算。
                mc.push(a + b);
                break;
            case'*':
                b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行乘法运算。
                mc.push(a * b);
                break;
            case'/':
                b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行除法运算。
                if (b == 0)//分母不能位0
                {
                    is_right = false;
                    return;
                }
                else
                    mc.push(a / b);
                break;
            default://获得数值
            {
                int sum = 0;
                if (is_number(mid))
                {
                    while (is_number(mid))
                    {
                        sum = sum * 10 + mid - '0';//字符到数字的改变
                        mid = sconed.front();
                        if (is_number(mid))
                            sconed.pop_front();
                    }
                    mc.push(sum);
                }
            }
            }
        }
    }
    Do_it

    3、GitHub源码;

     

  • 相关阅读:
    PHP面试系列之Linux(一) ----- Linux基础
    Redis入门(一)---安装
    获取主机ip地址
    Ubuntu安装Apache
    Ubuntu安装MySQL/MariaDB
    Ubuntu安装PHP7
    shell一次性执行多条命令
    将宿主主机上的目录挂载到Docker中
    bind 仿造 重写bind
    echars 饼状图 轮循 水平翻转
  • 原文地址:https://www.cnblogs.com/7750-13/p/7604604.html
Copyright © 2020-2023  润新知