表达式求值专题

首先要知道如何求逆波兰式(后缀表达式):

  表达式的表示形式有中缀、前缀和后缀3中形式。中缀表达式按操作符的优先级进行计算(后面代码实现只包括+、-、*、\,小括号),即数学运算。 后缀表达式中只有操作数和操作符。操作符在两个操作数之后。它的计算规则非常简单,严格按照从左到右的次序依次执行每一个操作。每遇到一个操作符,就将前面的两个数执行相应的操作。 
  由后缀表达式计算中缀表达式原理:计算机处理后缀表达式求值问题是比较方便的,即将遇到的操作数暂存于一个操作数栈中,凡是遇到操作数,便从栈中pop出两个操作数,并将结果存于操作数栈中,直到对后缀表达式中最后一个操作数处理完,最后压入栈中的数就是后最表达式的计算结果。 


 中缀表达式转换为等价的后缀表达式 
 中缀表达式不方便与计算机处理,通常要讲中缀表达式转换为一个与之等价的后缀表达式。等价是指两个表达式的计算顺序和计算结果完全相同。 
  中缀表达式:0.3/(5*2+1)# 的等价后缀表达式是:0.3 5 2 * 1 + /# 
  仔细观察这两个等价的表达式可知,操作数的出现次序是相同的,但运算符的出现次序是不同的。在后缀表达式中,运算符的出现次序是实际进行操作的次序;在中追表达式中,由于受到操作符的优先级和括号的影响,操作符出现次序与实际进行操作的次序很可能是不一样的。 


算法描述: 
  将中缀表达式转换为等价的后缀表达式的过程要使用一个栈放“(”,具体可以按照下面的方式进行。 
  (1)从左到右依次扫描中缀表达式的每一个字符,如果是数字字符和圆点“.”则直接将它们写入后缀表达式中。 
  (2)如果遇到的是开括号“(”,则将它们压入一个操作符栈(不需要与栈顶操作符相比较),它表明一个新的计算层次的开始,在遇到和它匹配的闭括号“)”时,将栈中的元素弹出来并放入后缀表达式中,直到栈顶元素为“(”时,将栈顶元素“(”弹出(不需要加入后缀表达式),表明这一层括号内的操作处理完毕。 
  (3)如果遇到的是操作符,则将该操作符和操作符栈顶元素比较: 
        1、当所遇到的操作符的优先级小于或等于栈顶元素的优先级时,则取 出栈顶元素放入后缀表达式,并弹出该栈顶元素,反复执行直到当前操作符的优先级大于栈顶元素的优先级小于;

        2、当所遇到的操作符的优先级大于栈顶元素的优先级的时则将它压入栈中。 

  (4)重复上述步骤直到遇到中缀表达式的结束符标记“#”,弹出栈中的所有元素并放入后缀表达式中,转换结束

                                                          ——copy from 飘过的小牛

 

得到后缀表达式,就不难计算表达式的值,如果是数字压入栈,当遇到运算符,弹出两个(双目)数字计算后再压栈,答案就是栈剩下的最后一个数字

 

代码:

/*
    表达式求值,逆波兰式(后缀表达式)算法
    输入(可以有空格,支持小数,实现'+-/*%'): ((1+2)*5+1)/4=
    注意:取模一定是要整型,实现版本数字全是double,强制类型转换可能倒置错误
    转换为后缀表达式: 得到:1 2 + 5 * 1 + 4 / =
    计算后缀表达式:得到:4.00
*/
struct Exp  {
    stack<char> op;
    stack<double> num;
    bool error;

    int prior(char ch)  {                           //运算符的优先级
        switch (ch) {
            case '+':
            case '-': return 1;
            case '*':
			case '%':
            case '/': return 2;
            default:  return 0;
        }
    }
    bool is_digit(char ch)  {
        return '0' <= ch && ch <= '9';
    }
    string get_postfix(string s)    {               //中缀表达式转变后缀表达式
        while (!op.empty ())    op.pop ();
        op.push ('#');
        string ret = "";
        int len = s.length (), i = 0;
        while (i < len)    {
            if (s[i] == ' ' || s[i] == '=')    {
                i++;    continue;
            }
            else if (s[i] == '(')    {
                op.push (s[i++]);
            }
            else if (s[i] == ')')   {
                while (op.top () != '(')    {
                    ret += op.top ();   ret += ' ';
                    op.pop ();
                }
                op.pop ();  i++;
            }
            else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/' || s[i] == '%')  {
                while (prior (op.top ()) >= prior (s[i]))    {
                    ret += op.top ();   ret += ' ';
                    op.pop ();
                }
                op.push (s[i++]);
            }
            else    {
                while (is_digit (s[i]) || s[i] == '.')  {
                    ret += s[i++];
                }
                ret += ' ';
            }
        }
        while (op.top () != '#') {
            ret += op.top ();   ret += ' ';
            op.pop ();
        }
        ret += '=';
        return ret;
    }
    double cal(double a, double b, char ch) {
        if (ch == '+')  return a + b;
        if (ch == '-')  return a - b;
        if (ch == '*')  return a * b;
        if (ch == '%')	return (int)((int)a % (int)b);
        if (ch == '/')  {
            if (b != 0) return a / b;
            error = true;   return 0;
        }
    }
    double solve(string str)    {                   //计算后缀表达式
        string s = get_postfix (str);
        while (!num.empty ())   num.pop ();
        error = false;
        int len = s.length (), i = 0;
        while (i < len)  {
            if (s[i] == ' ' || s[i] == '=') {i++;   continue;}
            else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/' || s[i] == '%')  {
                double a = num.top ();  num.pop ();
                double b = num.top ();  num.pop ();
                num.push (cal (b, a, s[i]));    i++;
            }
            else  {
                double x = 0;
                while (is_digit (s[i])) {
                    x = x * 10 + s[i] - '0';    i++;
                }
                if (s[i] == '.')    {
                    double k = 10.0, y = 0;
                    i++;
                    while (is_digit (s[i])) {
                        y += ((s[i] - '0') / k);
                        i++;    k *= 10;
                    }
                    x += y;
                }
                num.push (x);
            }
        }
        return num.top ();
    }
}E;

int main(void)    {
	ios::sync_with_stdio (false);						//如果全用流的话,加这句话能跑快点
    int T;  cin >> T;
    string str;	getline (cin, str);
    while (T--) {
        getline (cin, str);
		cout << E.get_postfix (str) << endl;
        cout << fixed << setprecision (6) << E.solve (str) << endl;
    }

    return 0;
}

 

 

拿着这个模板就可以解决:NYOJ_467_中缀式变后缀式NYOJ_35_表达式求值HDOJ_1237_简单计算器,以及ZSTOJ_4189_逻辑运算 ('!'是单目运算符)

 

转载于:https://www.cnblogs.com/Running-Time/p/4768431.html

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值