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

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

形式: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++]) != ‘\0‘)
    {
        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();
    }
}

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源码;

时间: 2024-08-29 05:13:24

简单计算机——逆波兰表达式的相关文章

逆波兰表达式的C实现

复习下数据结构,用栈简单实现逆波兰表达式,参考文档: http://www.nowamagic.net/librarys/veda/detail/2307 http://www.nowamagic.net/librarys/veda/detail/2306 直接上代码: /** *code by lichmama from cnblogs.com *@逆波兰表达式的C实现 *算术支持的运算模式: * 四则运算: * 操作数不得大于9: * 中间数(即运算当中的临时变量)不得超过127 **/ #

【算法】逆波兰表达式

表达式一般由操作数(Operand).运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间, 这称为中缀表达式(Infix Expression),如A+B. 波兰数学家Jan Lukasiewicz提出了另一种数学表示法,它有两种表示形式: 把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB: 把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Express

逆波兰表达式——中缀表达式转后缀表达式

逆波兰表达式 先说一下中缀表达式,平时我们使用的运算表达式就是中缀表达式,例如1+3*2,中缀表达式的特点就是:二元运算符总是置于与之相关的两个运算对象之间 人读起来比较好理解,但是计算机处理起来就很麻烦,运算顺序往往因表达式的内容而定,不具规律性 后缀表达式,后缀表达式的特点就是:每一运算符都置于其运算对象之后,以上面的中缀表达式1+2*3为例子,转为后缀表达式就是123*+ 下面先分析怎么把中缀表达式转换为后缀表达式,这里我们考虑六种操作符'+'.'-'.'*'.'/'.'('.')',完成

lintcode 中等题:Evaluate Reverse Polish notation逆波兰表达式求值

题目 逆波兰表达式求值 在逆波兰表达法中,其有效的运算符号包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰计数表达. 样例 ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 ["4", "13", "5", "/", "+"]

续前篇-关于逆波兰表达式的计算

相对于逆波兰表达式的转换,逆波兰表达的计算可谓简单不少. 具体计算方法参考:http://www.cnblogs.com/vpoet/p/4659546.html 这里也大致梳理一下: 1.新建一个栈将逆波兰表达式的数字依次压入栈中 2.当遇到运算符时,出栈两个数同时将运算结果压栈 3.重复步骤2直到计算计算,栈中的元素即为逆波兰表达式的计算结果. 实现如下: 1 #include <iostream> 2 #include <stack> 3 using namespace st

逆波兰表达式(后缀表达式)

前/中/后缀表达式的转换 自然表达式转换为前/中/后缀表达式,其实是很简单的.首先将自然表达式按照优先级顺序,构造出与表达式相对应的二叉树,然后对二叉树进行前/中/后缀遍历,即得到前/中/后缀表达式. 举例说明将自然表达式转换成二叉树: a×(b+c)-d ① 根据表达式的优先级顺序,首先计算(b+c),形成二叉树 ②然后是a×(b+c),在写时注意左右的位置关系 ③最后在右边加上 -d 然后最这个构造好的二叉树进行遍历,三种遍历的顺序分别是这样的: ① 前序遍历:根-左-右 ② 中序遍历:左-

波兰、逆波兰表达式

软考习题里遇到了这样一道题,给出了一个逆波兰式,让求它对应的中缀表达式. 逆波兰式:ab-cd+* ,它的中缀表达式是(a-b)*(c+d) 思考: 这让我蒙圈了,这是为什么呢.怎么得到的呢,应该有什么规律的吧. 首先我们要知道: 波兰式:前缀表达式 逆波兰式:后缀表达式 了解这三个表达式之前,我们需要知道 表达式 解释 例子 前缀 不含括号的的算数表达式,将运算符写在前面,操作数写在后面 *+ 2 1 3 中缀 必须含括号,操作符处于操作数的中间 (2+1)*3 后缀 不含括号,运算符放在两个

【LeetCode刷题Java版】Evaluate Reverse Polish Notation(计算逆波兰表达式)

Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, *, /. Each operand may be an integer or another expression. Some examples: ["2", "1", "+", "3", "*"] -&g

逆波兰表达式的实现(也叫后缀表达式)

本文主要偏重实现如何将字符串表达式转换为逆波兰表达式. 关于其讲解参考我转载的一篇博文:http://www.cnblogs.com/vpoet/p/4659546.html 先说说优先级: ()    +-     */%(从左到右递增) 下面先简单再梳理一下: 1.建立两个栈,一个为N(数据栈),一个为OP(运算符栈) 2.将字符串从左向右遍历,把数据压入数据栈,把运算符压入运算符的栈   关于运算符压栈的规则:⑴ 如果OP为空直接将运算符压入栈 ⑵ 如果不为空,则比较待入栈元素和栈顶元素的