【数据结构与算法】双栈法解决表达式计算问题

这篇具有很好参考价值的文章主要介绍了【数据结构与算法】双栈法解决表达式计算问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、基本计算器Ⅰ

题目链接

题目描述:

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

示例 1:

输入:s = “1 + 1”
输出:2

示例 2:

输入:s = " 2-1 + 2 "
输出:3

示例 3:

输入:s = “(1+(4+5+2)-3)+(6+8)”
输出:23

提示:

1 <= s.length <= 3 * 105
s 由数字、‘+’、‘-’、‘(’、‘)’、和 ’ ’ 组成
s 表示一个有效的表达式
‘+’ 不能用作一元运算(例如, “+1” 和 “+(2 + 3)” 无效)
‘-’ 可以用作一元运算(即 “-1” 和 “-(2 + 3)” 是有效的)
输入中不存在两个连续的操作符
每个数字和运行的计算将适合于一个有符号的 32位 整数

思路分析
用两个栈:
nums:存数字字符
ops:存符号字符

从前向后遍历字符串,因为这道题只有+/-,所以不用考虑符号优先级问题。
遍历过程有以下几种情况:

1️⃣ 空格:直接跳过
2️⃣ 数字字符:向后遍历取出完整数字,放入nums中。
3️⃣ (:直接放入ops中,等待)与之匹配
4️⃣ ):利用两个栈计算,直到遇到(,结果放入nums中,再把(出栈
5️⃣ +/-先把前面能计算的都计算了(一直算到遇到(为止),结果放入nums中,符号放入ops中

关于首字符带符号的处理:
可以先往nums中加一个0元素,这样-就可以算进去。

关于(+(-的处理:
每次遇到+/-的时候判断前一个字符是否是(,如果是就往nums中添加0。

关于空格的处理:
这里不能遇到空格后跳过,因为可能出现"1-( -2)"这种情况,所以先预处理字符串把空格全部消掉。

代码如下:文章来源地址https://www.toymoban.com/news/detail-498620.html

class Solution {
public:
    stack<int> nums;
    stack<char> ops;

    unordered_map<char, function<int(int, int)>> hash = {
        {'+', [](int x, int y){return x + y;}},
        {'-', [](int x, int y){return x - y;}},
    };

    void delBlack(string& s)
    {
        auto it = s.find(" ");
        while(it != -1)
        {
            s.replace(it, 1, "");
            it = s.find(" ");
        }
    }

    void calc()
    {
        if(nums.size() < 2 || ops.empty()) return;
        int right = nums.top();
        nums.pop();
        int left = nums.top();
        nums.pop();
        char op = ops.top();
        ops.pop();
        nums.push(hash[op](left, right));
    }
    
    int calculate(string s) {
        // 去掉空格
        delBlack(s);
        // 防止首元素为-
        nums.push(0);
        int n = s.size();
        for(int i = 0; i < n; i++)
        {
            if(isdigit(s[i]))// 数字字符
            {
                int cur = 0, j = i;
                while(j < n && isdigit(s[j]))
                {
                    cur = cur * 10 + (s[j++] - '0');
                }
                nums.push(cur);
                i = j - 1;
            }
            else// 符号字符
            {
                if(s[i] == '(') ops.push(s[i]);
                else if(hash.count(s[i]))// + -
                {
                    // "(+"情况
                    if (i > 0 && (s[i - 1] == '(')) 
                    {
                        nums.push(0);
                    }
                    // 入栈前先把前面的计算了
                    while(ops.size() && ops.top() != '(')
                    {
                        calc();
                    }
                    ops.push(s[i]);
                }
                else// ')'
                {
                    // 一直算到 '('
                    while(ops.size() && ops.top() != '(')
                    {
                        calc();
                    }
                    ops.pop();
                }
            }
        }
        while(!ops.empty())
            calc();
        return nums.top();
    }
};

二、基本计算器Ⅱ

题目链接

题目描述:

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

示例 1:

输入:s = “3+2*2”
输出:7

示例 2:

输入:s = " 3/2 "
输出:1

示例 3:

输入:s = " 3+5 / 2 "
输出:5

提示:

1 <= s.length <= 3 * 105
s 由整数和算符 (‘+’, ‘-’, ‘*’, ‘/’) 组成,中间由一些空格隔开
s 表示一个 有效表达式
表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1] 内
题目数据保证答案是一个 32-bit 整数

思路分析:
这道题跟上面一道题多了一个符号优先级问题,为了解决这个问题,可以加入一个符号优先级表:

unordered_map<char,int> oper_pri = {
        {'+',1},
        {'-',1},
        {'*',2},
        {'/',2},
};

当遇到符号+ - * /的时候先判断优先级oper_pri[ops.top()] >= oper_pri[s[i]]的时候说明可以计算前面的表达式了,先计算前面的,然后再把符号添加进ops中。

那遇到)也要计算前面的,需不需要判断优先级呢?
不需要,因为再()内部已经自动处理完了。

代码如下:

class Solution {
public:
    stack<int> nums;
    stack<char> ops;

    unordered_map<char, function<int(int, int)>> hash = {
        {'+', [](int x, int y){return x + y;}},
        {'-', [](int x, int y){return x - y;}},
        {'*', [](int x, int y){return x * y;}},
        {'/', [](int x, int y){return x / y;}},
    };

    unordered_map<char,int> oper_pri = {
            {'+',1},
            {'-',1},
            {'*',2},
            {'/',2},
    };

    void delBlack(string& s)
    {
        auto it = s.find(" ");
        while(it != -1)
        {
            s.replace(it, 1, "");
            it = s.find(" ");
        }
    }

    void calc()
    {
        if(nums.size() < 2 || ops.empty()) return;
        int right = nums.top();
        nums.pop();
        int left = nums.top();
        nums.pop();
        char op = ops.top();
        ops.pop();
        nums.push(hash[op](left, right));
    }

    int calculate(string s) {
        // 去掉空格
        delBlack(s);
        // 防止首元素为-
        nums.push(0);
        int n = s.size();
        for(int i = 0; i < n; i++)
        {
            if(isdigit(s[i]))// 数字字符
            {
                int cur = 0, j = i;
                while(j < n && isdigit(s[j]))
                {
                    cur = cur * 10 + (s[j++] - '0');
                }
                nums.push(cur);
                i = j - 1;
            }
            else// 符号字符
            {
                if(s[i] == '(') ops.push(s[i]);
                else if(hash.count(s[i]))// + - * /
                {
                    // "(+"情况
                    if (i > 0 && (s[i - 1] == '(')) 
                    {
                        nums.push(0);
                    }
                    // 入栈前先把前面的计算了
                    while(ops.size() && ops.top() != '(' && oper_pri[ops.top()] >= oper_pri[s[i]])
                    {
                        calc();
                    }
                    ops.push(s[i]);
                }
                else// ')'
                {
                    // 一直算到 '('
                    while(ops.size() && ops.top() != '(')
                    {
                        calc();
                    }
                    ops.pop();
                }
            }
        }
        while(!ops.empty())
            calc();
        return nums.top();
    }
};


到了这里,关于【数据结构与算法】双栈法解决表达式计算问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构与算法——二叉树+带你实现表达式树(附源码)

    📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段, 因为最近参加新星计划算法赛道(白佬),所以加快了脚步,果然急迫感会增加动力 ——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的 📖作者主页:king南星 📖

    2024年01月25日
    浏览(48)
  • 数据结构——基于二叉树的表达式求值算法

    1.输入一个表达式(表达式中的数均小于10的正整数),利用二叉树来表示该表达式,创建表达式数,然后利用二叉树的遍历操作求表达式的值。 2.输入要求:多组数据,每组数据1行,为一个表达式,表达式以“=”结尾。当输入只有一个“=”时,输入结束。 3.输出要求:每组

    2024年02月04日
    浏览(46)
  • 【夜深人静学数据结构与算法 | 第二篇】后缀(逆波兰)表达式

    目录 前言:  中缀表达式:  后缀表达式: 中缀表达式转后缀表达式: 后缀表达式计算结果: 总结:  计算机在计算四则运算的时候,由于括号以及运算优先级的存在,并不能够很好的处理所有的运算,为了处理这种情况,我们引入了后缀表达式来优化算法。         

    2024年02月13日
    浏览(53)
  • 北京林业大学数据结构实验二 基于栈的算术表达式求值算法

    参见课本P75 例3.3

    2024年02月06日
    浏览(46)
  • C语言 / 数据结构中出现报错: 表达式必须包含算数或指针类型,但他具有类型 “XXX” 。 报错问题的解决 以及 方法

    前提介绍:L3 是一个结构体的地址,是一个指针  elem是该结构体内的一个结构体元素,elem是一个数组 算数类型是什么? 下该文章最下面 报错显示, 表达式必须包含 算数 或 指针类型 , 但elem是一个数组,它的类型明显不是指针类型, 那么elem 的类型本质上应该就是一个算

    2024年02月09日
    浏览(43)
  • 【算法】递归解决各种数据结构的遍历问题

    对于递归算法,我们最先想到的应该就是用递归的方式去中序遍历一棵树,递归的使用使得我们可以先深入到下层中,然后慢慢的输出下层的元素之后输出上层元素。 因此,基于此,我们甚至可以使用递归来逆序输出一个栈,链表等数据结构。 使用递归输出树 使用递归逆序

    2024年02月08日
    浏览(65)
  • 数据结构之表达式求值

     前言 运用堆栈解决表达式的求值,代码思路为: 1.定义两个栈,一个char类型的栈用于存放运算符(ysf)一个int类型的栈用于存放操作数(czs) 如一个表达式3+6*9,将“+”,“*”入ysf栈,将“3”“6”“9”入czs栈 2.运用getchar进行数据的录入,如果接收的是运算符,将其插入到运

    2024年04月29日
    浏览(34)
  • 数据结构 实验2——表达式求值

    一、实验名称:表达式求值 二、实验学时: 6 学时 三、实验目的 1.理解栈的结构特点和基本操作特性; 2.掌握利用栈实现表达式求值算法。 四、实验内容 ( 步骤 ) 输入一个算术表达式(以“=”结束),求其值。要求表达式以“=”结束,操作数为多位实数,对错误表达式要进行

    2023年04月08日
    浏览(38)
  • 数据结构 | 后缀表达式【深入剖析堆栈原理】

    Hello,大家好,国庆的第二天,带来的是数据结构中堆栈部分的后缀表达式,这也是一块有关栈的应用方面困扰了众多同学的一个大难题,今天就让我们一起解决这个难题📕 后缀表达式也称为 逆波兰表达式 ,也就是将算术运算符放在操作数的后面 例如【1 + 2 * 3】的后缀表达

    2023年04月27日
    浏览(46)
  • 【数据结构】12 堆栈应用:表达式求值

    有一个常量表达式的中缀表达式为:5 + 6 / 2 - 3 * 4,其后缀形式表示为: 5 6 2 / + 3 4 × -。后缀表达式的特点是运算符位于两个预算数之后。其前缀表达式为: - + 5 / 6 2 × 3 4。 后缀表达式相比于中缀表达式的求值要容易很多。 从左到右扫描该表达式: (1)遇见运算数5 6 2时不

    2024年02月20日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包