中缀表达式求解

问题描述:

中缀表达式计算,只包含加减乘除以及括号,例如:

2+3*4-5/2 = 11.5

((2+3*4)-5)/2 = 4.5

思路:

  1. 维护两个栈空间:数字栈与符号栈

  2. 注意入栈与出栈的规则,符号栈入栈时,根据符号优先级判断是否入栈或出栈。

高优先级符号后入栈时直接放入即可,低优先级符号后入栈时先弹出高优先级符号,优先级如下:

( < +- < * / < )

    普通操作符弹出计算时,只进行一次pop_cal操作。

    右括号出栈时,必须循环计算至左括号出栈为止。

边界case:

  1. 分母为0,assert处理。

  2. 数字范围超出变量上下限。

知识点:

  1. 栈操作:围绕出栈入栈操作分解问题,分解成cal计算函数、push_xxx压栈操作、pop_cal出栈计算操作、push_check入栈检查优先级等几步,逻辑会更清晰。

  2. 字符处理:用stringstream简化处理逻辑,string -> float, float -> string,多次使用之间需要clear() & str(""),重置标识以及清空字符串两个操作。

难度:★★★★

  1. 代码量大

  2. 需要考虑的细节多:字符处理、边界case、符号优先级、右括号特殊处理

  3. 熟悉栈操作

  

伪码:

 1 #include <stack>
 2 #include <string>
 3 #include <sstream>
 4 #include <iostream>
 5 #include <assert.h>
 6 #include <ctype.h>
 7
 8 using namespace std;
 9
10 stack<string> nums; //数字栈
11 stack<char> exps;   //操作符栈
12
13 //主函数:计算中缀表达式
14 float cal_res(const string &express)
15 {
16     //是否新数字
17     bool new_num = true;
18     //循环读取表达式字符
19     for(size_t i = 0; i < express.size(); i++)
20     {
21         //处理数字
22         if( isdigit( express[i] ) )
23         {
24             //数字压栈
25             push_num(express[i], new_num);
26             new_num = false;
27         }
28         else
29         {
30             //操作符压栈
31             push_exp( express[i] );
32             new_num = true;
33         }
34     }
35     //循环出栈,计算结果
36     float res = 0.0;
37     while( exps.size() > 0 )
38     {
39         pop_cal( res );
40     }
41     return res;
42 }
43
44 //压入数字栈
45 void push_num(char exp, bool new)
46 {
47     //...
48 }
49
50 //压入操作符栈
51 void push_exp(char exp)
52 {
53     //...
54 }
55
56 //检查入栈优先级
57 bool push_check(char exp)
58 {
59     //...
60 }
61
62 //出栈一次并计算结果,返回当前出栈操作符
63 char pop_cal(float &res)
64 {
65     //...
66 }

转载请注明引用自:

  http://www.cnblogs.com/breakthings/p/4049575.html

  

时间: 2024-10-12 00:15:18

中缀表达式求解的相关文章

表达式的计算(中缀表达式转为后缀表达式或逐步计算)

算数表达式的计算,也是很基础的一个问题.花了点时间写了下. 网上很多正确代码.但没有详细说明.虽然不复杂,但是还是写详细点.只有仔细思考过.问题才会在头脑中,觉得简单. 基本有2种方法. 1)中缀表达式转为后缀表达式,是最简洁有力的方法. 2)符合人的计算思路的逐步方法,不推荐使用,只适合锻炼下逻辑能力. 一.中缀表达式转为后缀表达式,是最简洁有力的方法. //更简洁通用的算法,就是把中缀表达式转换为后缀表达式.后缀表达式:不包含括号,运算符放在两个运算对象的后面. //一,无括号的n级符号算法

中缀表达式转后缀表达式---栈--二叉树---四则运算

我们平常书写的四则运算表达式属于中缀表达式,形式为"9+(3-1)*3+10/2",因为所有的运算符号都在两操作数之间,所以称为中缀表达式.我们使用中缀表达式来计算表达式的值,不过这种形式并不适合计算机求解.接下来,我们将中缀表达式转化为后缀表达式,所谓的后缀表达式就是操作符位于操作数后面的不包含括号的算数表达式,也叫做逆波兰表达式. 1)首先介绍一种人工的转化方法(http://www.cnblogs.com/MichaelYin/archive/2012/05/02/2479248

刁肥宅详解中缀表达式求值问题:C++实现顺序/链栈解决

1. 表达式的种类 如何将表达式翻译成能够正确求值的指令序列,是语言处理程序要解决的基本问题,作为栈的应用事例,下面介绍表达式的求值过程. 任何一个表达式都是由操作数(亦称运算对象).操作符(亦称运算符)和分界符组成的.通常,算术表达式有3种表示: ①中缀(infix)表示:<操作数><操作符><操作数>,如A+B. ②前缀(prefix)表示: <操作符><操作数><操作数>,如+AB. ③后缀(postfix)表示: <操作

关于中缀表达式的计算 和算符优先算法

中缀表达式计算:http://blog.sina.com.cn/s/blog_3fe961ae0100niq3.html 算符优先算法:http://blog.csdn.net/zhibudefeng/article/details/6937375 前中后缀表达式:http://blog.csdn.net/antineutrino/article/details/6763722/

适用于实数范围的中缀表达式的 + - * / ( ) 计算(C++实现)

核心算法: mid=FormatMid(mid); //格式化中缀表达式 JudgeLegalMid(mid); //判断中缀表达式的合法性 MidToPost mtp(mid); mtp.ToPost(post); //中缀表达式转后缀表达式 cout <<"结果:" <<Calc(post) <<endl; //计算后缀表达式 具体过程-- 第一步:格式化中缀表达式 这一步的目的是为了解决"-"的歧义问题:有时候"-

中缀表达式与前、后缀表达式转化简单的技巧[转]

35,15,+,80,70,-,*,20,/ //后缀表达方式 (((35+15)*(80-70))/20)=25 //中缀表达方式 /,*,+,35,15,-,80,70, 20 //前缀表达方式 人的思维方式很容易固定~~!正如习惯拉10进制.就对2,3,4,8,16等进制不知所措一样~~! 人们习惯的运算方式是中缀表达式.而碰到前缀,后缀方式..迷茫其实仅仅是一种表达式子的方式而已(不被你习惯的方式) 我这里教你一种也许你老师都没跟你讲的简单转换方式 一个中缀式到其他式子的转换方法 这里我

利用stack完成中缀表达式的四则运算

分析: 中缀表达式的操作符以中缀的形式处于操作数的中间. 若创建一个数字栈,一个运算符栈,并将一个中缀表达式从左至右压入栈这两个栈中.先向数字栈压入一个数字,再向运算符栈压入一个运算符,接着向数字栈压入数字.此时数字栈中有两个元素,字符栈中有一个元素. 当开始读到第二个运算符时就判断当前准备压入运算符与之前已在栈中运算符的优先级顺序,若栈顶的运算符优先顺序大于或等于当前即将压入的运算符,则弹出两个数字栈中的元素和一个运算符栈中的元素进行运算,将结果重新压回数字栈中,然后将当前的读到的运算符压入数

中缀表达式转为后缀表达式

** * 中缀表达式转后缀表达式 * * 作用:将一长串计算表达式转换为计算机易于操作的字符序列,用于计算器的设计 *  * 参与转换运算符 * +-/*()^% * * * 使用StringBuilder来保存转换出的后缀表达式 * 使用栈来操作运算符 * * * 转换原则 * 1.上述字符中()没有优先级值,+-优先级值为1,/*%优先级值为2,^优先级值为3 * 2.对于一个待计算的表达式,从左向右逐个检查每个字符 * 3.遇到数字,直接append到StringBuilder * 4.遇

中缀表达式转后缀表达式的方法:

1.遇到操作数:直接输出(添加到后缀表达式中)2.栈为空时,遇到运算符,直接入栈3.遇到左括号:将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出.5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈6.最终将栈中的元素依次出栈,输出.例如a+b*c+(d*e+f)*g ----> abc*+de*f+g*+ 遇到a:直接输出:后缀表达式:a堆栈:空 遇到+:堆栈:空,所以+入栈后缀表达式:a堆栈:+遇到b: 直