首页 > 其他分享 >3302. 表达式求值

3302. 表达式求值

时间:2023-09-27 15:22:44浏览次数:43  
标签:操作数 优先级 入栈 栈顶 运算符 求值 3302 表达式 op

3302. 表达式求值

题目: 3302. 表达式求值 - AcWing题库

“表达式求值”问题,两个核心关键点:

(1)双栈,一个操作数栈,一个运算符栈;

(2)运算符优先级,栈顶运算符,和,即将入栈的运算符的优先级比较:
如果栈顶的运算符优先级低,新运算符直接入栈

以1+2+3x4x5举例,看是如何利用上述两个关键点实施计算的。

首先,这个例子只有+和*两个运算符,所以它的运算符表是:

00.webp.jpg

这里的含义是:

(1)如果栈顶是+,即将入栈的是+,栈顶优先级高,需要先计算,再入栈;

(2)如果栈顶是+,即将入栈的是*,栈顶优先级低,直接入栈;

(3)如果栈顶是*,即将入栈的是+,栈顶优先级高,需要先计算,再入栈;

(4)如果栈顶是*,即将入栈的是*,栈顶优先级高,需要先计算,再入栈;

有运算符后,再进行字符串的读入

01.webp.jpg

一开始,初始化好输入的字符串,以及操作数栈,运算符栈。

02.webp.jpg

一步步,扫描字符串,操作数一个个入栈,运算符也入栈。

3.png

下一个操作符要入栈时,需要先比较优先级。

栈内的优先级高,必须先计算,才能入栈。

4.webp.jpg

计算的过程为:

(1)操作数出栈,作为num2;

(2)操作数出栈,作为num1;

(3)运算符出栈,作为op;

(4)计算出结果;

接下来,运算符和操作数才能继续入栈。下一个操作符要入栈时,继续比较与栈顶的优先级。

栈内的优先级低,可以直接入栈。

7.png

字符串继续移动。

8.png

又要比较优先级了。

9.webp.jpg

栈内的优先级高,还是先计算(3*4=12),再入栈。

10.png

不断入栈,直到字符串扫描完毕。

11.webp.jpg

不断出栈,直到得到最终结果3+60=63,算法完成。

如果栈顶的运算符优先级高,先出栈计算,新运算符再入栈

这个方法的时间复杂度为O(n),整个字符串只需要扫描一遍。

运算符有+-*/()~^&都没问题,如果共有n个运算符,会有一个n*n的优先级表。

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

const int N = 1e5 + 10;
stack<int> num;
stack<char> op;
//优先级表 注意这里是undered_map
unordered_map<char, int> h{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};

//比较优先级后,如果需要弹出两个数字和操作符 则计算需要弹出的两个数字
void eval()
{
    int a = num.top(); //第二个操作数
    num.pop();
    
    int b = num.top(); //第一个操作数
    num.pop();
    
    char p = op.top(); //运算符
    op.pop();
    int ans = 0;
    if(p == '+')  ans = b + a;
    if(p == '-')  ans = b - a;
    if(p == '*')  ans = b * a;
    if(p == '/')  ans = b / a;
    
    num.push(ans); //结果入栈
 }


int main()
{
    string s;  //读入表达式
    cin >> s;
    
    
    for(int i = 0; i < s.size(); i++)
    {
        if(isdigit(s[i])) //数字入栈
        {
            int x = 0, j = i;  //计算数字
            
            while(j < s.size() && isdigit(s[j]))
            {
                x = x * 10 + s[j] - '0';
                j++;
            }
            num.push(x);
            i = j - 1;  //j 多加了一次  注意这里是i = j - 1
        }
        else if(s[i] == '(')  //左括号无优先级 直接入栈
        {
            op.push(s[i]);
        }
        else if(s[i] == ')')  //右括号  需要匹配到左括号
        {
            while(op.top() != '(')  //一直计算到左括号
                eval();
            op.pop();
        }
        else
        {
            //带入栈运算符优先级低  则优先计算栈内的
            while(op.size() && h[op.top()] >= h[s[i]])
                eval();
           	op.push(s[i]); //操作符入栈
        }
    }
    
    while(op.size())  //剩余的入栈
        eval();
   
    cout << num.top() << endl; //输出结果
    return 0;
}

标签:操作数,优先级,入栈,栈顶,运算符,求值,3302,表达式,op
From: https://www.cnblogs.com/encore051/p/17732797.html

相关文章

  • MySQL正则表达式:模式匹配、中文匹配、替换、提取字符串
    在MySQL中,使用REGEXP或RLIKE操作符进行正则表达式匹配,而使用NOTREGEXP或NOTRLIKE操作符进行不匹配。一些常用的MySQL正则表达式语法:匹配字符:.:匹配任意字符(除了换行符)。[]:匹配方括号中的任意字符。[^]:匹配不在方括号中的任意字符。匹配重复:*:匹配零个或多个前面的字符。+:匹配一个......
  • lambda表达式递归报错
    lambda表达式递归报错报错代码:voidsolve(){intn=10;vector<int>adj[n+1];autodfs=[&](autoself,intu,intp)->void{for(autov:adj[u]){}};}在递归lambda表达式中引用的外部变量尽量不要出现形如......
  • jmeter正则表达式提取
    参考:https://www.cnblogs.com/uncleyong/p/10779268.html正则表达式提取器:后置处理器-正则表达式提取器Applyto:一般保持默认选择Mainsampleonly,这个用得最多,如果有sub-samples,可以选择第一个选项要检查的响应字段:用得最多的是主体,即header+body,可以从响应头,也可以从响应体......
  • Spring Boot 目录遍历--表达式注入--代码执行--(CVE-2021-21234)&&(CVE-2022-22963)&&
    SpringBoot目录遍历--表达式注入--代码执行--(CVE-2021-21234)&&(CVE-2022-22963)&&(CVE-2022-22947)&&(CVE-2022-2296)SpringBoot目录遍历(CVE-2021-21234)漏洞简介spring-boot-actuator-logview是一个简单的日志文件查看器作为SpringBoot执行器端点,在0.2.13版本之前存......
  • 算术表达式求值法(表达式求值)之前序表示法求值
    概念前序表示法,也称为前缀表示法或波兰表示法(Polishnotation),是一种用于表示数学表达式和算术运算的方法。这种表示法的特点是将运算符置于操作数之前,而不是像传统的中缀表示法(例如,2+3)将运算符置于操作数之间。前序表示法具有一些优点,尤其在计算机科学和计算器设计中非常有用。......
  • 正则表达式输入中文英文名
    请输入正确的姓名,支持中文或者英文(20位字符内),例如:杨颖/^([\u4e00-\u9fa5]{1,20}|[a-zA-Z\.\s]{1,20})$/如果想要支持名字中间输入·和.这样写,例如:迪丽热巴·迪力木拉提/^[\u4e00-\u9fa5a-zA-Z·.]+$/......
  • 正则表达式
    #按照邮件地址的格式(用户名@域名.后缀)来编写正则表达式#该正则表达式中包含了四个部分:#1.用户名:由一个或多个字母、数字、下划线、点、减号组成,且必须以字母或数字开头(用于描述用户名的部分用小括号括起来)#2.@符号:该部分只包含一个@符号#3.域名:由一个或多个字母、数字......
  • Java 8 Lambda 表达式解析
    Lambda表达式,也可称为闭包,它是推动Java8发布的最重要新特性。使用Lambda表达式可以使代码变的更加简洁紧凑。坦白的说,初次看见Lambda表达式瞬间头就大了,为了更好的理解,我们可以把Lambda表达式当作是一种匿名函数(对Java而言这并不完全正确,但现在姑且这么认为),简单地说,就是......
  • 算术表达式的表示法(即求值法)
    说明算术表达式的表示法有多种,其中最常见的包括中缀表达法、前缀表达法和后缀表达法。这些表示法用于表示和求解数学表达式,它们在计算机科学和数学领域都有广泛的应用。中缀表达法、前缀表达法和后缀表达法是操作符的位置来分类的。操作符位于2个操作之间叫中缀表达法,操作符位于......
  • Bash-正则表达式
    一.正则表达式与通配符通配符:用来匹配符合条件的文件名(完全匹配),ls、find、cp这些命令不支持正则表达式,所以只能用通配符正则表达式:用来匹配符合条件的字符串(包含匹配),grep、awk、sed等命令支持正则表达式常用通配符:*(任意字符重复任意多次)、?、[]二.基础正则表达式*(匹配前一个......