【双栈】有括号的四则运算求值

已通过的题目

题目都一样,稍微改一下输入。代码通过了以下 3 题的测试数据。其中,LeetCode的两题的测试数据不够复杂(下面说明)。代码的正确性,还需要更多的测试数据来测。

224. 基本计算器

227. 基本计算器 II

题目 1683: 算法3-4:表达式求值

LeetCode 227 题的测试数据,没有包含以下两种情况:

1、负数开头。类似:-2+...

2、左括号后的第一个数是负数。类似:2*(-3+4)...

另外,如果有LeetCode会员,可以再提交一下这题:772. 基本计算器 III

代码

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

// 装数字的栈
stack<int> num;
// 装符号的栈。从栈底到栈顶方向,符号运算优先级越高
// 优先级越高,越要优先计算
// ) < +、- < *、/ < (
stack<char> opr;
// 存储符号优先级
map<char, int> prio;

void initPriority() {
    prio[')'] = 1;
    prio['+'] = 2;
    prio['-'] = 2;
    prio['*'] = 3;
    prio['/'] = 3;
    prio['('] = 4;
}

// 双目运算符的计算。c:中间的符号;a:左边的数;b:右边的数
int cal(int a, int b, char c) {
    if (c=='+') {
        return a+b;
    } 
    if (c=='-') {
        return a-b;
    }
    if (c=='*') {
        return a*b;
    } 
    if (c=='/') {
        return a/b;
    }
    return 0;
}

void doCal() {
	char c = opr.top();  opr.pop();
    int b = num.top();  num.pop();
    int a = num.top();  num.pop();
    int res = cal(a, b, c);
    num.push(res);
}

// 特殊情况:-1+...
// (-2+3-...)  
// 2+(3-2+1)
// 2+(-2+1)*2/2  2+(2-1)*2  
// 1+2*3/2
int calculate(string s) {
    initPriority();
    
    // 防止开头是负数的情况 
    if (s[0]=='-') {
    	num.push(0);
	}
    
    int t=0; // 用于字符串转int值
    for(int i=0; i<s.length(); i++) {
    	if(s[i] == ' ') {
    		continue;
		}
        
        if (isdigit(s[i])) {  // 数字
            t = 10*t + (s[i]-'0');
            if (!isdigit(s[i+1])) { 
                num.push(t);
                t=0;
            }
        }  	
		else { // 符号
            while(!opr.empty() &&  opr.top()!='('  && prio[ s[i] ] <= prio[ opr.top() ]) {
            	doCal();
            }
            if (!opr.empty() && opr.top() == '(' && s[i]==')') {
            	opr.pop();
			} else {
				opr.push(s[i]);
				// 防止 (-2...的情况 
				if(s[i]=='(' && s[i+1]=='-') {
					num.push(0);
				}
			}
        }
    }
    while(!opr.empty()) {
       doCal(); 
    }
    return num.top();
}

int main() {
	string s;
	while(getline(cin, s)) {
		printf("%d\n", calculate(s));
	}
	
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值