计算器(表达式计算-后缀表达式实现)逆波兰表达式

本文介绍了如何使用逆波兰表达式(后缀表达式)来计算整数算术运算表达式。通过将中缀表达式转换成后缀表达式,然后利用栈的数据结构进行计算,遵循运算符的优先级。详细阐述了转换和计算过程,并提供了Java代码实现。
摘要由CSDN通过智能技术生成

【问题描述】

从标准输入中读入一个整数算术运算表达式,如24 / ( 1 + 2 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 )= ,计算表达式结果,并输出。
要求:
1、表达式运算符只有+、-、*、/,表达式末尾的=字符表示表达式输入结束,表达式中可能会出现空格;
2、表达式中会出现圆括号,括号可能嵌套,不会出现错误的表达式;
3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。
4、要求采用逆波兰表达式来实现表达式计算。

【输入形式】

从键盘输入一个以=结尾的整数算术运算表达式。操作符和操作数之间可以有空格分隔。

【输出形式】

在屏幕上输出计算结果(为整数,即在计算过程中除法为整除)。

【样例输入】

24 / ( 1 + 2 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 ) =

【样例输出】

18

【样例说明】

按照运算符及括号优先级依次计算表达式的值。


本问题的难点在于将中缀表达式转换成为后缀表达式(逆波兰表达式),我也是参考了若干文章,放在下面,需要自取:

前缀、中缀、后缀表达式(逆波兰表达式)

前缀表达式(波兰式),中缀表达式与后缀表达式(逆波兰式)

【数据结构与算法】逆波兰表达式、波兰表达式

利用后缀表达式求值:

遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素op 栈顶元素 ),并将结果入栈

重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果

示例:

计算后缀表达式的值:1 3 2 - 4 × +

(1)从左至右扫描,将1,3,2压入栈

(2)遇到-运算符,2和3弹出,计算3-2(这里注意不是2-3,是次顶元素 op 栈顶元素,所以是3-2,下面步骤的求值同理)的值,得到1,将1压入栈

(3)遇到4,将4压入栈

(4)遇到×运算符,弹出4和1,计算1×4的值,得到4,将4压入栈

(5)遇到+运算符,弹出4和1,计算1+4的值,得到5即为最终结果

我的理解

  将中缀表达式中表示运算先后顺序的括号转换成了先后顺序,也就是说后缀表达式中越靠前运算的优先级越高。在计算的时候,每遇见一个操作符(+, -, *, /),都会与前两个数字进行相应运算,直到最后。

  下面是我的具体实现思路:

  代码分成两大个模块,第一个是将输入的字符串转换为后缀表达式(逆波兰表达式),第二个是对第一个模块中产生的后缀表达式进行计算。得出最后的结果。
在第一个模块中,主要在函数:

 vector<int> rpn(string &s);

中实现,传入的参数就是输入进来的字符串(中缀表达式),返回值是一个int类型的vector,保存中缀表达式中的数字。在进行转化时,创建两个stack s1, s2;分别表示符号栈、后缀表达式的字符栈。由于输入进的算式中的数字可能不是一位数,那么在s2中我才用一个’d’表示这个位置上是一个数字,并将对应的数字保存进vector中。
  从左往右遍历输入的字符串,当遇到字符表示数字的时候,继续往后读,直到遇见非数字的字符,利用atoi函数将该字符串转换为int型后push_back在vector num,同时在后缀表达式字符栈s2中push一个’d’表示该位置是一个数字(digital);当遇见’(’时,直接将其push进s1符号栈;当遇到操作符(’+’, ’-’, ’*’, ’/’)时,当s1不为空时,将s1栈顶元素push到s2,直到遇见’*’, ’/’,因其二者优先级较高;当遇见’)’时,将s1中栈顶元素除了括号外都push到s2,直到遇见’(’;当遇到’=’时,表示运算式子已经读取完毕,这时候将s1符号栈中元素全部push到s2后,即可得到后缀表达式。
  在第二个模块中,只要以函数:

int calculate(string &s, vector<int> &num)

为主,参数为第一个模块产生的后缀表达式和数字队列,返回值为运算结果。在此函数中,创建一个stack res;表示中间的计算结果。在遍历后缀表达式时,如果遇到’d’表示一个数字,那么将num中对应位置的数据push到res中;如果遇见操作符,那么将res中栈顶两个元素pop出来进行相应的计算,并将结果push到res中。当后缀表达式遍历完成时,res中将只有一个元素即为结果。


完整的代码如下:

#include <bits/stdc++.h>
using namespace std;

vector<int> rpn(string &s)
{
   
    stack<char> s1, s2;
    vector<int> num;
    unsigned n = s.length();
    for (unsigned i = 0; i < n && s[i] != '='; i++)
    {
   
        if (isdigit(s[i]))
        {
   
            string tmp;
            tmp += s[i];
            while (isdigit(s[++i]))
                tmp += s[i];
            num.push_back(atoi(tmp.c_str()));
            s2.push('d'); //'d'表示此位置为一个数字
            i--;
        }
        else if (s[i] == '(')
            s1.push(s[i]);
        else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')
        {
   
            while (!s1.empty() && (s1.top() == '*' || s
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A91A981E

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值