中缀表达式求值

news2024/11/25 6:38:40

题目

  • 请写一个整数计算器,支持加减乘三种运算和括号。
    • 示例1
      输入:“1+2”
      返回值:3
    • 示例2
      输入:“(2*(3-4))*5”
      返回值:-10
    • 示例3
      输入:“3+2*3*4-1”
      返回值:26

思路

  • 经典的中缀表达式求值。常用思路,将其转为后缀表达式(后缀表达式的特点:遇到运算符则将前两个数拿出来运算,便于计算机计算),边转边求值。
  • 读到左括号 ( 较为特殊,读到左括号时直接入栈,
  • 本题中运算符优先级:左括号或栈顶为空、乘、加减 、右括号。
  • 读到右括号时一直出栈直到一个左括号出栈。

算法步骤

  • 遍历字符串,当 遍历到的字符是数字 时,直接将其压入数字栈。
  • 否则,当 遍历到的字符是运算符 时,判断字符,直到字符串读完:
    • 若符号栈为空,则直接将其压入符号栈。
    • 若符号栈非空,则判断符号栈栈顶的运算符优先级:
      • 若 遍历到的运算符符号的优先级 > 符号栈栈顶元素的优先级,或符号栈空,则将读取的运算符压入符号栈。
      • 若 遍历到的运算符符号的优先级 ≤ 符号栈栈顶元素的优先级,则将其出栈,并从数字栈弹出两个元素进行该运算,先弹出的为右操作数,后弹出的为左操作数,将结果压入数字栈。
  • 最后,若符号栈非空,则弹出栈顶元素,并从数字栈弹出两个元素来进行该运算,重复该操作直到符号栈空。
  • 符号栈为空后,弹出数字栈栈顶元素作为结果。
  • 返回数值站栈顶元素作为最终结果。
int solve(string s) {
    stack<char> sign;
    stack<int> num;
    for (int i = 0; i < s.length(); i++) 
    {
        //若当前遍历到的字符为数字,则将连续的数放入val栈
        if (s[i] >= '0' && s[i] <= '9') 
        {
            int rear = i;
            while ((rear + 1) < s.length() && s[rear + 1] >= '0' && s[rear + 1] <= '9') 
            {
                rear++;
            }
            int n = 0;
            for (int j = rear; j >= i; j--) {
                n += (s[j] - '0') * pow(10, (rear - j));
            }
            i = rear;
            num.push(n);
        }
        //【优先级较大】当前遍历到的字符为(、*  或  ops符号栈为空,则将该符号压入符号栈
        else if (s[i] == '(' || s[i] == '*'|| sign.size() == 0   )
        {
            sign.push(s[i]);
        }
        //【优先级较小】当前遍历到的字符为+、-
        else if (s[i] == '+' || s[i] == '-') 
        {
            while (1) 
            {
                if (sign.size() == 0)
                    break;
                if (sign.top() == '*') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 * n2);
                }
                else if (sign.top() == '+') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 + n2);
                }
                else if (sign.top() == '-') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 - n2);
                }
                else {
                    break;
                }
            }
            sign.push(s[i]);
        }
        // 读到右括号时符号栈就一直出栈直到一个左括号出栈。
        else if (s[i] == ')') 
        {
            while (1) 
            {
                if (sign.size() == 0) 
                {
                    break;
                }
                else if (sign.top() == '(') 
                {
                    sign.pop();
                    break;
                }
                else if (sign.top() == '+') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 + n2);
                }
                else if (sign.top() == '-') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 - n2);
                }
                else if (sign.top() == '*') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 * n2);
                }
            }
        }
    }
    //最后,若符号栈非空,则弹出栈顶元素,并从数字栈弹出两个元素来进行该运算。重复该操作直到符号栈空。
    while (sign.size() != 0) 
    {
        if (sign.top() == '+') 
        {
            sign.pop();
            int n2 = num.top();
            num.pop();
            int n1 = num.top();
            num.pop();
            num.push(n1 + n2);
        }
        else if (sign.top() == '-') 
        {
            sign.pop();
            int n2 = num.top();
            num.pop();
            int n1 = num.top();
            num.pop();
            num.push(n1 - n2);
        }
        else if (sign.top() == '*') 
        {
            sign.pop();
            int n2 = num.top();
            num.pop();
            int n1 = num.top();
            num.pop();
            num.push(n1 * n2);
        }
    }
    //弹出数字栈栈顶元素,即得结果。
    return num.top();
}

实例

#include <iostream>
#include <stack>
using namespace std;

int solve(string s) {
    // write code here
    stack<char> sign;
    stack<int> num;
    for (int i = 0; i < s.length(); i++) 
    {
        //若当前遍历到的字符为数字,则将连续的数放入val栈
        if (s[i] >= '0' && s[i] <= '9') 
        {
            int rear = i;
            while ((rear + 1) < s.length() && s[rear + 1] >= '0' && s[rear + 1] <= '9') 
            {
                rear++;
            }
            int n = 0;
            for (int j = rear; j >= i; j--) {
                n += (s[j] - '0') * pow(10, (rear - j));
            }
            i = rear;
            num.push(n);
        }
        //若 当前遍历到的字符为(、*  或  ops符号栈为空,则将该符号压入符号栈
        else if (s[i] == '(' || s[i] == '*'|| sign.size() == 0   )
        {
            sign.push(s[i]);
        }
        //若 当前遍历到的字符为+、-
        else if (s[i] == '+' || s[i] == '-') 
        {
            while (1) 
            {
                if (sign.size() == 0)
                    break;
                if (sign.top() == '*') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 * n2);
                }
                else if (sign.top() == '+') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 + n2);
                }
                else if (sign.top() == '-') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 - n2);
                }
                else {
                    break;
                }
            }
            sign.push(s[i]);
        }
        else if (s[i] == ')') 
        {
            while (1) 
            {
                if (sign.size() == 0) 
                {
                    break;
                }
                else if (sign.top() == '(') 
                {
                    sign.pop();
                    break;
                }
                else if (sign.top() == '+') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 + n2);
                }
                else if (sign.top() == '-') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 - n2);
                }
                else if (sign.top() == '*') 
                {
                    sign.pop();
                    int n2 = num.top();
                    num.pop();
                    int n1 = num.top();
                    num.pop();
                    num.push(n1 * n2);
                }
            }
        }
    }
    //最后,若符号栈非空,则弹出栈顶元素,并从数字栈弹出两个元素来进行该运算。重复该操作直到符号栈空。
    while (sign.size() != 0) 
    {
        if (sign.top() == '+') 
        {
            sign.pop();
            int n2 = num.top();
            num.pop();
            int n1 = num.top();
            num.pop();
            num.push(n1 + n2);
        }
        else if (sign.top() == '-') 
        {
            sign.pop();
            int n2 = num.top();
            num.pop();
            int n1 = num.top();
            num.pop();
            num.push(n1 - n2);
        }
        else if (sign.top() == '*') 
        {
            sign.pop();
            int n2 = num.top();
            num.pop();
            int n1 = num.top();
            num.pop();
            num.push(n1 * n2);
        }
    }
    //弹出数字栈栈顶元素,即得结果。
    return num.top();
}

int main()
{
    string mys = "1+3*(5+2)";
	cout<< mys<<"=" << solve(mys) << endl;
	
    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1604805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu 20.04.06 PCL C++学习记录(二十六)

[TOC]PCL中点云配准模块的学习 学习背景 参考书籍&#xff1a;《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,&#xff0c;PCL版本为1.10.0&#xff0c;CMake版本为3.16&#xff0c;可用点云下载地址 学习内容 在代码中使用ICP迭代最近点算法&#xff0c;程序随机…

游戏前摇后摇Q闪E闪QE闪QA等操作

备注&#xff1a;未经博主允许禁止转载 个人笔记&#xff08;整理不易&#xff0c;有帮助&#xff0c;收藏点赞评论&#xff0c;爱你们&#xff01;&#xff01;&#xff01;你的支持是我写作的动力&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_w…

负荷预测 | Matlab基于TCN-LSTM-Attention单变量时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.负荷预测 | Matlab基于TCN-LSTM-Attention单变量时间序列多步预测&#xff1b; 2.单变量时间序列数据集&#xff0c;采用前12个时刻预测未来96个时刻的数据&#xff1b; 3.excel数据方便替换&#xff0c;运行环境ma…

请陪伴Kimi和GPT成长

经验的闪光汤圆 但是我想要写实的 你有吗&#xff1f; 岁数大了&#xff0c;希望如何学习新知识呢&#xff1f;又觉得自己哪些能力亟需补强呢&#xff1f; 看论文自然得用Kimi&#xff0c;主要是肝不动了&#xff0c;眼睛也顶不住了。 正好昨天跟专业人士学会了用工作流的办法跟…

buuctf之ciscn_2019_c_1

ciscn_2019_c_1 一、查看属性二、静态分析三、动态分析四、思路五、exp 一、查看属性 首先还是必要的查看属性环节&#xff1a; 可以知道该文件是一个x86架构下的64位小端ELF文件&#xff0c;开启了栈不可执行&#xff08;NX&#xff09; 执行一下&#xff0c;先有一个选择&…

树莓派+Openwrt连接校园网,打破校园网设备限制

前言 因为本校学生校园网只允许最多三个设备登录&#xff0c;对于同时拥有多个联网设备的我十分不友好&#xff0c;而且大多单片机如esp32的wifi模块是只允许一般的WPA/WPA2认证的&#xff0c;是不支持校园网的portal认证。所以我决定搞一个路由器。 然后我上网买了一个TP-Li…

加密软件作用有哪些?迅软DSE加密系统满足企业防泄密需求

加密软件在保护个人隐私、商业机密、敏感数据等方面发挥着重要作用&#xff0c;为用户和组织提供了重要的安全保障措施。保护数据的安全性和隐私性。通过加密软件&#xff0c;用户可以对文件、图纸、文档、源代码等进行加密处理&#xff0c;使其变得不可读取&#xff0c;只有授…

java动态代理--JDK代理

1.概述 JDK动态代理&#xff1a;只能代理实现了接口的类&#xff0c;代理对象是实现了目标对象所有接口的代理类 使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来创建代理对象&#xff0c;工作通过反射机制完成。 2.实现接口InvocationHandler …

37、Tomato(VulnHub)

Tomato 一、nmap 2211是ssh的端口&#xff0c;21的ftp也不是弱密码 二、web渗透 随便看看 目录爆破 /seclists/Discovery/Web-Content/common.txt /antibot_image/antibots/readme.txt 发现该站点存在反爬机制 /antibot_image/antibots/info.php 提示我们该网页存在个参数 GET&…

汇编语言——将DX,AX组成的32位数逻辑左移3位

data segment data ends stack segment stacktop label worddw 100 dup (?) stack ends code segmentassume cs:code,ds:data,ss:stack main proc farmov ax,datamov ds,axmov ax,stackmov ss,axlea sp,top;0000 0001 1100 1010 | 0000 0010 0001 1111;逻辑左移三位后&#xf…

VsCode调试远程服务器上面的Docker容器

第一步 VsCode 连接ssh 下载安装VsCode(Visual Studio Code)&#xff0c;首次安装会提示你安装Chinese(Simplified)中文简体&#xff0c;安装完后重新打开就是汉化界面了。在左边侧边栏找到扩展选项&#xff0c;然后安装Remote Development插件&#xff0c;里面包含了Remote S…

FAT16文件系统

FAT16 大端存储&#xff1a;高位字节放在低地址端&#xff0c;低位字节放在高地址端。 小端存储&#xff1a;低位字节放在低地址端&#xff0c;高位字节放在高地址端。 举一个例子&#xff0c;比如数字0x12 34 56 78在内存中的表示形式为&#xff1a; 大端模式&#xff1a; 低地…

【Gradle】Gradle的构建过程

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置&#xff0c;也增加了基于Kotlin语言的kotlin-based DSL&#xff0c;抛弃了基于XML的各种繁琐配置。 面向Java应用为主。当前其支持的语言C、J…

二、pwn - 零基础ROP之PIE保护绕过-碰撞

欲学本文,先看前文:一、pwn - 零基础ROP之Android ARM 32位篇(新修订,精华篇)-CSDN博客 代码、文件同第一篇,自行复制。本文唯一区别在于,我们不利用vulnerable_function打印的地址,无法定位pie base地址,直接随机碰撞(爆破)~ 有一定比例成功的可能,贴近实战! 多…

终于总结出一套小红书万能涨粉公式

新手做小红书&#xff0c;最关心的除了变现、提升流量、应该就是涨粉了。 但关于小红书涨粉&#xff0c;小伙伴表示难如登天&#xff0c;臣妾做不到啊。 别担心&#xff0c;小易拆解近100个博主账号后&#xff0c;终于总结出小红书涨粉公式&#xff0c;垂直不违规干货人设活跃…

IDEA2024配置RunDashBoard(Services)面板

IDEA2024配置RunDashBoard(Services)面板 新版本的IDEA没有RunDashBoard&#xff0c;取而代之的是Services面板&#xff0c;不需要配置workspace.xml文件; 本文教你简单的方法就能一个SpringBoot的Main运行多次&#xff0c;方便调试。 1、配置启动类 导航栏&#xff0c;Edit…

基于SpringBoot的“外卖点餐系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“外卖点餐系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能图 用户功能界面 订单管理界面 配送单管…

IO基础合集

IO基础合集 1. File类1.1 概述1.2 构造方法1.3 常用方法获取功能的方法绝对路径和相对路径判断功能的方法创建删除功能的方法 1.4 目录的遍历 2. IO概述2.1 什么是IO2.2 IO的分类2.3 IO的流向说明图解2.4 顶级父类们2.5 IO流体系结构 3. 字节流3.1 一切皆为字节3.2 字节输出流【…

PTA 编程题(C语言)-- 特殊a串数列求和

题目标题&#xff1a; 判断素数 题目作者&#xff1a;颜晖 浙大城市学院 给定两个均不超过9的正整数a和n&#xff0c;要求编写程序求aaaaaa⋯aa⋯a&#xff08;n个a&#xff09;之和。 输入格式&#xff1a; 输入在一行中给…

Java项目:基于SSM框架实现的心遗非遗文创电商平台(源码+数据库)

一、项目简介 本项目是一套基于SSM框架实现的心遗非遗文创电商平台 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…