首页 > 其他分享 >中缀表达式求值(栈的应用)

中缀表达式求值(栈的应用)

时间:2023-11-27 13:55:06浏览次数:28  
标签:opt 中缀 ++ while 取整 求值 表达式 op

一、题目来源

AcWing算法基础课-3302.表达式求值

二、题目描述

给定一个表达式,其中运算符仅包含 +,-,*,/(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。

注意:

  • 数据保证给定的表达式合法。
  • 题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2) 之类表达式均不会出现。
  • 题目保证表达式中所有数字均为正整数。
  • 题目保证表达式在中间计算过程以及结果中,均不超过 \(2 ^ {31} - 1\)。
  • 题目中的整除是指向 \(0\) 取整,也就是说对于大于 \(0\) 的结果向下取整,例如 \(5/3=1\),对于小于 \(0\) 的结果向上取整,例如 \(5/(1−4)=−1\)。
  • C++和Java中的整除默认是向零取整;Python中的整除//默认向下取整,因此Python的eval()函数中的整除也是向下取整,在本题中不能直接使用。

输入格式

共一行,为给定表达式。

输出格式

共一行,为表达式的结果。

数据范围

表达式的长度不超过 \(10^5\)。

输入样例:

(2+2)*(1+1) 

输出样例:

8 

三、算法思路

本题是中缀表达式求值问题,主要为栈的应用。

思路如下:

  • 首先,设置两个栈,一个为操作符栈,一个为数字栈。
  • 然后,遍历整个序列:
    • 遇到 '(' ,直接 \(push\)
    • 遇到数字,直接 \(push\)
    • 遇到操作符
      • 如果是 '+'、‘-’,那么都可以算
        • \(while\) 栈不空 且 栈顶不是'('
          • 操作
      • 如果是 '*'、'/',那么加减不能先算,只能算乘除
        • \(while\) 栈不空 且 栈顶是 '*'、'/'
          • 操作
      • 最后 \(push\)
    • 遇到 ')'
      • \(while\) 栈顶不是 '('
        • 操作
      • 将 '(' 弹出
  • 处理 操作符栈中 剩余的操作符
  • 数字栈的栈顶为最终答案

注意事项:

  • 遇到数字要 \(push\),但是数字可能不是个位数,显然有可能是多位数(但不会是负数),所以需要处理一下。
  • 可以将判断是否是数字、加减、乘除、操作这些抽象成函数,这样代码好写一些。
  • 一定要注意,加减的运算级比乘除低,所以遇到加减可以算之前的乘除,而遇到乘除不能先算之前的加减,例如 \(2+3*5\),如果搞错了就会得出 \(25\),读者自行思考。
  • 遍历完之后别忘了将剩余的操作符都要处理掉。

四、源代码

#include <iostream>

using namespace std;

const int N = 100010;

char op[N];
int num[N];
int opt, numt;

void init()
{
    opt = 0;
    numt = 0;
}

bool isDigit(char c)
{
    if (c >= '0' && c <= '9')   return true;
    return false;
}

bool isAddOrSub(char c)
{
    if (c == '+' || c == '-')   return true;
    return false;
}

bool isMulOrDiv(char c)
{
    if (c == '*' || c == '/')   return true;
    return false;
}

void func()
{
    char c = op[-- opt];
    int num1 = num[-- numt], num2 = num[-- numt];
    
    int res = 0;
    if (c == '+')   res = num2 + num1;
    else if (c == '-')  res = num2 - num1;
    else if (c == '*')  res = num2 * num1;
    else    res = num2 / num1;
    
    num[numt ++ ] = res;
}

int main()
{
    string s;
    cin >> s;
    
    init();
    
    for (int i = 0; i < s.size(); ++i)
    {
        if (s[i] == '(')    op[opt ++ ] = s[i];
        else if (isDigit(s[i]))
        {
            int res = 0, j = i;
            while (j < s.size() && isDigit(s[j]))
                res = res * 10 + s[j ++ ] - '0';
                
            num[numt ++ ] = res;
            
            i = j - 1;
        }
        else if (isAddOrSub(s[i]) || isMulOrDiv(s[i]))
        {
            if (isAddOrSub(s[i]))
                while (opt != 0 && op[opt - 1] != '(')
                    func();
            else
                while (opt != 0 && isMulOrDiv(op[opt - 1]))
                    func();
        
            op[opt ++ ] = s[i];
        }
        else
        {
            while (op[opt - 1] != '(')  func();
            opt -- ;
        }
    }
    
    while (opt != 0)    func();
    
    cout << num[numt - 1] << endl;
    
    return 0;
}

标签:opt,中缀,++,while,取整,求值,表达式,op
From: https://www.cnblogs.com/grave-master/p/17855583.html

相关文章

  • 透析Java本质的36个话题02运算符与表达式
    1.莫衷一是——i+++j该如何计算?三个加号​ 在java中默认前面结合也就是(i++)+jinti=25;intj=2;intresult=i+++j;System.out.println(i);System.out.println(j);/*262*/贪心规则编译器的贪心规则,分析符号......
  • shell变量类型--read--if语句正侧表达式(扩展)文本处理器、awk命令
    变量:是容器,值是可变的,变化的。作用就是增强脚本的灵活性。各种shell环境中都使用了“变量”的概念。shell变量用来存放系统和用户需要使用的特定参数(值),而且这些参数可以根据用户的设定或系统环境的变化而相应变化。通过使用变量,shell程序能够提供更加灵活的功能,适应性更强。变量(数......
  • shell变量类型--read--if语句正侧表达式(扩展)文本处理器、awk命令
    变量:是容器,值是可变的,变化的。作用就是增强脚本的灵活性。各种shell环境中都使用了“变量”的概念。shell变量用来存放系统和用户需要使用的特定参数(值),而且这些参数可以根据用户的设定或系统环境的变化而相应变化。通过使用变量,shell程序能够提供更加灵活的功能,适应性更强。变量(数......
  • 逆波兰表达式(后缀表达式)
    逆波兰表达式1.后缀表达式首先将逆波兰的数字和符号分割开来,再通过将后缀表达式放到ArrayList中,然后配合栈来完成计算。后缀表达式计算结果过程1.如果是数则直接入栈,通过正则表达式取数(包含多位数)2.如果是运算符,则先弹出两个数,运算完成后(注意减法和除法后弹出数是被减数/被除......
  • 正则表达式RE
    1.正则表达式(regularexpression,RE)是一种字符模式,用于在查找过程中匹配指定的字符。2.在大多数程序里,正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式,它将匹配被查找的行中任何位置出现的相同模式。在正则表达式中,#元字符是最重要的概念。#正则......
  • python 正则表达式
    一、校验数字的表达式数字:^[0-9]*$n位的数字:^\d{n}$至少n位的数字:^\d{n,}$m-n位的数字:^\d{m,n}$零和非零开头的数字:^(0|[1-9][0-9]*)$非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$正数、......
  • 如何写出高效率的正则表达式
    如果纯粹是为了挑战自己的正则水平,用来实现一些特效(例如使用正则表达式计算质数、解线性方程),效率不是问题;如果所写的正则表达式只是为了满足一两次、几十次的运行,优化与否区别也不太大。但是,如果所写的正则表达式会百万次、千万次地运行,效率就是很大的问题了。我这里总结了几条提升......
  • 7-2 栈实现表达式求值
    #include<iostream>#include<cstdio>#include<string>usingnamespacestd;constintN=100010;stringsplit(strings){    stringss;    for(inti=0;i<s.size();i++){        if(s[i]==32)continue;        ss+=char(s[i]);    }  ......
  • 常用正则表达式
    正文:MDN正则参考文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions我的正则笔记:https://www.yuque.com/docs/share/36f69420-115f-4e01-b897-550d94b404ab?#《正则》千分位表示价格1.针对正数、负数,整数,浮点数都可以(IE不支持,会出现错......
  • Java正则表达式从入门到精通​
    Java正则表达式从入门到精通JAVA正则表达式规则Java中的正则表达式规则,在java.util.regex.Pattern类文档中有详细说明。字符类匹配符(只匹配一个字符)规则字符说明[abc]匹配a,b或c中的任意一个字符[^abc]除a,b或c之外的任意一个字符(取反)[a-zA-Z]包含在a到z或A到Z范围内的任意一个字符(......