求后缀表达式(逆波兰表达式)及求他的值实现简单计算器

问题描述:


 实现思路:


使用栈实现一个求逆波兰表达式的函数,求出表达式后,再通过逆波兰表达式的求值算法,再通过栈求出表达式的值。求值方法见力扣的150题:

实现代码:


#include <iostream>
#include <string>
#include <vector>
#include <stack>

class Solution {
private:
    std::stack<float> ans;//求结果的栈
    std::stack<char> pre_notation;//求后缀表达式的栈
    std::vector<std::string> reversePolishNotation;//后缀表达式
private:
    bool isNumber(char& str) {//判断数字
        return !(str == '+' || str == '-' || str == '*' || str == '/' || str == '(' || str == ')');
    }
    bool isNumber(std::string& str) {//判断数字
        return !(str == "+" || str == "-" || str == "*" || str == "/" || str == "(" || str == ")");
    }
public:
    float evacuateReversePolishNotation(std::string& str) {//计算后缀表达式的值
        while (!ans.empty()) {ans.pop();}//清除原有的元素
        std::string temp = str;
        gainReversePolishNotation(temp);
        for (int i = 0; i < reversePolishNotation.size(); ++i) {
            std::string& s = reversePolishNotation[i];
            if (isNumber(s)) {
                ans.push(std::stol(s));
            } else {
                float num1 = ans.top();
                ans.pop();
                float num2 = ans.top();
                ans.pop();
                switch(s[0]) {
                    case '*' : ans.push(num1 * num2);break;
                    case '/' : ans.push(num2 / num1);break;
                    case '+' : ans.push(num1 + num2);break;
                    case '-' : ans.push(num2 - num1);break;
                }
            }
        }
        return ans.top();
    }

    void gainReversePolishNotation(std::string& str) {//求后缀表达式
        while (!pre_notation.empty()) {pre_notation.pop();}//清除原有的元素
        reversePolishNotation.clear();
        for (int i = 0; i < str.size(); ++i) {
            if (str[i] != ' ') {//如果不是空格
                char& temp = str[i];
                if (isNumber(temp)) {//如果该字符是数字
                    std::string post_str;
                    post_str.push_back(temp);
                    while (str[i+1] != ' ' && isNumber(str[i + 1]) && i + 1 < str.size()) {//可能数字不止一位
                        post_str.push_back(str[++i]);
                    }
                    reversePolishNotation.push_back(post_str);
                } else {//如果该字符不是数字
                    std::string temp_str;
                    switch (temp) {
                        case '*' ://乘法,直到弹出栈顶遇到的所有*和/,然后推入*
                            while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*')) {
                                std::string post_str;
                                post_str.push_back(pre_notation.top());
				                reversePolishNotation.push_back(post_str);//推入后缀表达式
				                pre_notation.pop();
			                }
                            pre_notation.push(temp); 
                            break;
                        case '/' ://除法,直到弹出栈顶遇到的所有*和/,然后推入/
                            while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*')) {
                                std::string post_str;
                                post_str.push_back(pre_notation.top());
				                reversePolishNotation.push_back(post_str);//推入后缀表达式
				                pre_notation.pop();
			                }
                            pre_notation.push(temp); 
                            break;
                        case '-' ://减法,直到弹出栈顶遇到的所有*和/和+和-,然后推入-  
                            while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*' || pre_notation.top() == '+'|| pre_notation.top() == '-')) {
                                std::string post_str;
                                post_str.push_back(pre_notation.top());
				                reversePolishNotation.push_back(post_str);//推入后缀表达式
				                pre_notation.pop();
			                }
                            pre_notation.push(temp);
                            break;
                        case '+' ://加法,直到弹出栈顶遇到的弹出所有*和/和+和-,然后推入+
                            while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*' || pre_notation.top() == '-' || pre_notation.top() == '+')) {
                                std::string post_str;
                                post_str.push_back(pre_notation.top());
				                reversePolishNotation.push_back(post_str);//推入后缀表达式
				                pre_notation.pop();
			                }
                            pre_notation.push(temp);
                            break;
                        case ')' :  //遇到右括号,执行出栈操作,输出到后缀表达式,直到弹出的是左括号
                            while (!pre_notation.empty() && pre_notation.top() != '('){
                                std::string post_str;
                                post_str.push_back(pre_notation.top());
				                reversePolishNotation.push_back(post_str);//推入后缀表达式
				                pre_notation.pop();
			                }
			                pre_notation.pop();//弹出左括号
                            break;
                        case '(' ://遇到左括号,入栈  
                            pre_notation.push(temp); 
                            break;
                    }
                }
            } else {//如果是空格
                continue;
            }
        }
        while (!pre_notation.empty()) {//剩余内容推入后缀表达式
            std::string post_str;
            post_str.push_back(pre_notation.top());
		    reversePolishNotation.push_back(post_str);
		    pre_notation.pop();
        }
    }
};

int main() {
    std::vector<std::string> inputs;
    std::string temp;
    std::getline(std::cin, temp);
    while (temp != "0") {
        inputs.push_back(temp);
        std::getline(std::cin, temp);
    }
    Solution* ans = new Solution();
    for (int i = 0; i < inputs.size(); ++i) {
        printf("%.2f\n", ans->evacuateReversePolishNotation(inputs[i]));
    }
    delete ans;

    return 0;
}

备注:


代码纯自己手撸,由于hdu目前不开了,所以也没法提交代码验证正确性。具体求后缀表达式的思路和方法大家参见别人的博客。如有错误欢迎指出(应该没有吧,改了一下午了233)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值