逆波兰表达式的生成及计算

来源:互联网 发布:淘宝介入处理流程 编辑:程序博客网 时间:2024/06/07 09:02
逆波兰表达式(后缀表达式)生成算法:
(1)构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。

(2)读入一个用中缀表示法表示的简单算术表达式,为方便起见,认为地在字符串后面加入一个特殊字符“;”,并设其优先级为0。

(3)从左至右扫描该算术表达式的每一个字符,如果该字符是数字,则分析到该数字串的结束并将该数字串加入结果字符串,小数点亦算入数字串。

(4)如果该字符是运算符,则按如下操作:

  如果该字符是左括号“(”,则该字符直接压入运算符栈。

  如果该字符是右括号“)”,则把运算符栈顶元素弹出直至第一次遇到左括号。

  如果该字符是算术运算符且其优先关系高于运算符栈顶的运算符,则将该运算符入栈。

  否则,将栈顶的运算符从栈中弹出至结果字符串末尾,直至栈顶运算符的优先级低于当前运算符,并将该字符入栈。

(5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式(遇到特殊字符“;”)。

如:

一般简单表达式:((4+5)*6-5)/2+3*2

逆波兰表达式:4 5 + 6 * 5 - 2 / 3 2 * +

步骤如下:

  运算符栈 结果字符串

第1步: ; ""

第2步: ;( ""

第3步: ;(( ""

第4步: ;(( "4"

第5步: ;((+ "4 5"

第6步: ;( "4 5 +"

第7步: ;(* "4 5 +"

第8步: ;(* "4 5 + 6"

第9步: ;(- "4 5 + 6 *"

第10步: ;(- "4 5 + 6 * 5"

第11步: ; "4 5 + 6 * 5 -"

第12步: ;/ "4 5 + 6 * 5 -"

第13步: ;/ "4 5 + 6 * 5 - 2"

第14步: ;+ "4 5 + 6 * 5 - 2 /"

第15步: ;+ "4 5 + 6 * 5 - 2 / 3"

第16步: ;+* "4 5 + 6 * 5 - 2 / 3"

第17步: ;+* "4 5 + 6 * 5 - 2 / 3 2"

第18步: ;+ "4 5 + 6 * 5 - 2 / 3 2 *"

第19步: ; "4 5 + 6 * 5 - 2 / 3 2 * +"

其中运算符优先级如下:

* / :2

+ - :1

; :0

逆波兰表达式求值算法:

(1)构建一个操作数栈,类型为float;

(2)依次扫描逆波兰表达式的每一项;

(3)如果是数字串则压入操作数栈;

(4)如果是运算符,则从操作数栈顶弹出两个操作数,与运算符进行运算,结果压入操作数栈。(计算减法和除法时需要注意数字的先后)

(5)不断重复以上步骤直至扫描完逆波兰表达式。

(6)此时操作数栈必定只剩一个数据,即为逆波兰表达式的值,弹出输出。 

如:如上表达式计算结果为:30.5

逆波兰表达式生成及求值的C++实现:

#include<stdio.h> #include<math.h> #include<iostream>#include<stack>#include<map>#include<string.h>#include<string>#include<stdlib.h>#include<sstream>using namespace std;typedef struct{string s;int type;     //0:operatorChar;1:number}expNode;float calPoland(stack<expNode> t);int operatorPriority(char c){switch(c){case '#':return 1;case '+':case '-':return 2;case '*':case '/':return 3;default:return 1;}}float calculate(float a,float b,char c){switch(c){case '+':return a+b;case '-':return a-b;case '*':return a*b;case '/':return a/b;default:; }}stack<expNode>  makePoland(string t){int len=t.length(),i; char c;stack<expNode> expStack;stack<char> charStack;charStack.push('#');for(i=0;i<len;i++){c=t[i]; if(c=='(') {              charStack.push(c);}else if(c==')'){while(1){c=charStack.top();charStack.pop();if(c=='(')break;expNode node;node.s.append(1,c);node.type=0;expStack.push(node);}}else if(c>='0'&&c<='9'){expNode node;node.s.append(1,c);node.type=1;while(1){if(t[i+1]>='0'&&t[i+1]<='9'&&i<len){node.s.append(1,t[i+1]);i++;}else break;} expStack.push(node);}else if(operatorPriority(c)>operatorPriority(charStack.top())) {charStack.push(c);}else if(operatorPriority(c)<=operatorPriority(charStack.top()))  {while(1){char topc=charStack.top();if(operatorPriority(c)>operatorPriority(topc)){charStack.push(c);break;}expNode node;node.s.append(1,topc);node.type=0;expStack.push(node);charStack.pop();}}printf("%d :",i);stack<expNode> x=expStack;while(!x.empty()){expNode node=x.top();cout<<node.s<<' ';x.pop();}  printf("\n");}while(!charStack.empty()){c=charStack.top();charStack.pop();if(c=='#')break;expNode node;node.s.append(1,c);node.type=0;expStack.push(node);}stack<expNode> x=expStack;while(!expStack.empty())expStack.pop();while(!x.empty()){expNode node=x.top();x.pop();expStack.push(node);}  /*while(!expStack.empty()){expNode node=expStack.top();cout<<node.s;expStack.pop();} printf("\n"); *///printf("%f\n",calPoland(expStack));return expStack; }float calPoland(stack<expNode> t){stack<float> numStack;int x=t.size();while(!t.empty()){expNode node=t.top();t.pop();if(node.type==1){float num;istringstream iss(node.s);iss>>num;numStack.push(num);}else if(node.type==0){float a=numStack.top();numStack.pop();float b=numStack.top();numStack.pop();char c=node.s[0];float ans=calculate(b,a,c);numStack.push(ans);}else {printf("error:expStack type error!\n");}}float ans=numStack.top();return ans;}int main(){//string s="((44+55)*66-5)/22+3*2" ;string s="((4+5)*6-5)/2+3*2" ;stack<expNode> expStack=makePoland(s);float ans=calPoland(expStack);printf("%f\n",ans);}





0 0
原创粉丝点击