表达式求值(递归和栈)

来源:互联网 发布:mac unix 可执行文件 编辑:程序博客网 时间:2024/05/29 09:30

问题:输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。

输入格式
  输入一行,包含一个表达式。
输出格式
  输出这个表达式的值。
样例输入
1-2+3*(4-5)
样例输出
-4
数据规模和约定
  表达式长度不超过100,表达式运算合法且运算过程都在int内进行。

1.用递归的方式:


#include<iostream>#include<cctype>using namespace std; int expression();//表达式 int term();//项 int factor();//因子 int main(){cout << expression() <<endl;return 0;}int expression(){int result = term();char c = cin.peek();while(c == '+' || c == '-'){cin.get();if(c == '+')result += term();else if(c == '-')result -= term();c = cin.peek();}return result;}int term(){int result = factor();char c = cin.peek();while(c == '*' || c == '/'){cin.get();if(c == '*')result *= factor();if(c == '/')result /= factor();c = cin.peek();}return result;}int factor(){int result = 0;char c = cin.peek();if(c == '('){cin.get();result += expression();cin.get();}else while(isdigit(c)){cin.get();result = result * 10 + c - '0';c = cin.peek();}return result;}


2.用栈的方式

(1):首先设置操作数栈为空栈,设置运算符栈以‘#’为栈底元素(其优先级最低)。

(2):通过为栈内栈外运算符设置值而比较其优先级

(3):依次去找到表达式中的所有运算符和操作数,对于操作数直接入栈,运算符则和运算符栈的栈顶运算进行比较优先级,若栈内优先级大,则进行相应操作并操作数和栈内运算符都出栈,若优先级相等只需栈内运算符出栈继续查找下一个运算符即可,若栈内优先级低则栈外运算符入栈。依次循环知道分析完表达式中的所有运算符和操作数可。

(4):最后在操作数栈中将只会剩下唯一的一个元素,而该元素也将就会是所求表达式的值。



#include<iostream>#include<stack>#include<string>#include<cstdlib>using namespace std;/*判断符号间的优先关系函数*1表示>,0表示=,-1表示<*c1栈内的算符,c2栈外的算符*/int Judge(char c1,char c2){int a1,a2;if('+'==c1||'-'==c1) a1 = 3;if('*'==c1||'/'==c1)a1 = 5;if('('==c1) a1 = 1;if(')'==c1) a1 = 7;if('#'==c1) a1 = 0;if('+'==c2||'-'==c2)a2 = 2;if('*'==c2||'/'==c2)a2 = 4;if('('==c2) a2 = 6;if(')'==c2) a2 = 1;if('#'==c2) a2 = 0;if(a1>a2) return 1;if(a1==a2) return 0;  //只有(),#才可能相等 if(a1<a2) return -1;}//符号运算函数double run(char c ,double d1,double d2){switch (c){case '+':return d1+d2;break;case '-':return d1-d2;break;case'*' :return d1*d2;break;case '/':return d1/d2;break;default:return 0.0;break;}}int main(){char op[9] = "+-*/()#";string str ;cin>>str;//给表达式字符串str添加'#'结束标识符str.append(1,'#'); //string &append(int n,char c):在当前字符串结尾添加n个字符cstack<char> OPTR;//运算符栈stack<double> OPND;//操作数栈int a = -1;//先将#符号入栈OPTR.push('#');while(true){ int b = a+1; a = str.find_first_of(op,a+1);//s.find_first_of(letter, pos)),意思是在s中寻找首个letter中有的字符,从pos开始搜索 if(a==string::npos) break; //npos 是一个常数,用来表示不存在的位置 if(a!=b) { string ss(str,b,a-b); double d=atof(ss.c_str());//atof()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结                                   //束时('\0')才结束转换,并将结果返回;将字串转换成浮点型数 //数据先入栈 OPND.push(d); } //运算符优先级比较 int ju = Judge(OPTR.top(),str[a]); if(-1==ju)//栈外优先级大直接入栈 {     OPTR.push(str[a]); } if(0==ju)//后括号遇到前括号直接出栈  { OPTR.pop(); } if(1==ju)//栈内优先级大,出栈进行运算 { double d1 = OPND.top(); OPND.pop(); double d2 = OPND.top(); OPND.pop(); d1 = run(OPTR.top(),d2,d1); //运算结果入栈 OPND.push(d1); OPTR.pop(); a--;  //表达式的下标  }}//删除表达式最后的'#'结束标识符str.erase(str.length()-1,1);cout<<OPND.top()<<endl;}





1 0
原创粉丝点击