中缀表达式(Infix Notation)的求解,只考虑双目运算符情况

来源:互联网 发布:网络盒子 电视直播 编辑:程序博客网 时间:2024/06/09 13:42

最近看了数据结构的书,刚刚学到栈,其中的一大应用就是求中缀表达式的值,于是实现了一个。(书上的代码错误好多)

 

先要说明一下:
1、什么是栈结构
2、什么是中缀表达式

 

栈(stack,也叫堆栈)
Wikipedia:http://en.wikipedia.org/wiki/Stack_(abstract_data_type)

 

栈是一种抽象数据结构(ADT, Abstract Data Type),可以比喻为只有一个出口的仓库,属于 Last-In-First-Out 结构,先进入的元素保存在栈底,后进入的元素依次从栈底向栈顶放置;当一个栈非空的时候,只能依次从栈顶取出元素。所以栈结构是先入后出的。

栈的操作主要有两种:入栈(Push,也有叫 压入,进栈等的),出栈(Pop,也有叫 弹出的)。
如果一个栈使用链式结构,那么整个栈的容量只取决于内存允许的容量。

 

中缀表达式(InfixNotation)
Wikipedia:http://en.wikipedia.org/wiki/Infix_notation

 

这是最常见的表达式,表达式就是用运算符连接起来有运算意义的式子,比如:
1+5*(2+1)

 

常见运算符(operator)有 + - * / % ^ ( )
而参与运算的叫做操作数(oprand),比如例子中的 1 5 2 1


由于运算符有优先级,所以一个表达式的求值需要考虑那两个运算符先运算,那两个后运算的问题。

但是如果从左向右读取表达式,然后根据运算符的先后顺序,再利用栈就可以求得一个表达式的值。

 

中缀表达式的运算规则如下:
·根据运算符优先级由高到低的顺序进行运算
·有括号出现时先算括号内的,后算括号外的,多层括号,由内向外进行
·乘方连续出现时先算最右面的

 

运算符之间存在如下比较关系
 * The operators' priority is show below:
(Comparison direction: Opt2 to Opt1)

运算符比较 opt2       op1^*/+-()#^>>>>><>>*<>>>><>>/<>>>><>>+<<<>><>>-<<<>><>>(<<<<<<= )>>>>> >>#<<<<<< =

 

注意这些比较符左边为 opt1 右边为 opt2。

 

中缀表达式求值需要两个栈,操作数栈 s1,和运算符栈 s2

 

实现过程为:
1.置操作数栈 s1 为空栈,运算符栈 s2 中预设一个最低级的运算符 '#'


2.依次从左向右读入表达式的每一个字符


3.如果当前字符是操作数,入操作数栈 s1


4.如果当前字符是运算符,则:
 1)若这个运算符 θ2 比栈顶运算符 θ1 优先级高,则入运算符栈 s2,转到 2
 2)若这个运算符 θ2 比栈顶运算符 θ1 优先级低,则从操作数栈 s1 弹出两个操作数,从运算符栈 s2 弹出一个运算符进行运算,并将其结果压入操作数栈 s1,并转到 3
 3)若这个运算符 θ2 与栈顶运算符 θ1 的优先级相同,从操作符栈 s2 弹出栈顶元素,并转到 2


5.直到遇到结束符 '#'

 

以下是运行结果:

 

附上代码:

堆栈(模板)

template <class T>class StackNode{public:T value;StackNode *next;StackNode(T d=0){value=d;next=NULL;}};template <class T>class LinkStack{StackNode<T> *top;public:LinkStack(){top=new StackNode<T>();top->next=NULL;}~LinkStack();void Push(T value);//Push value into stackT Pop();//Pop value out of stackT GetTop();//Get the top node's value without pop itbool IsEmpty();//whether the stack is emptyvoid Clear();//Clear the stack;};template <class T>LinkStack<T>::~LinkStack(){StackNode<T> *p=NULL;while (!IsEmpty()){p=top->next;top->next=p->next;delete p;}delete top;}template <class T>void LinkStack<T>::Push(T value){StackNode<T> *p=NULL;p=new StackNode<T>(value);p->next=top->next;top->next=p;//cout<<"Push: "<<value<<endl;}template <class T>T LinkStack<T>::Pop(){if (top->next!=NULL){StackNode<T> *p=top->next;T retvalue=p->value;top->next=p->next;delete p;//cout<<"Pop: "<<retvalue<<endl;return retvalue;}else{cerr<<"The stack is empty."<<endl;return 0;}}template <class T>T LinkStack<T>::GetTop(){if (top->next!=NULL){return (top->next->value);}else{cerr<<"The stack is empty."<<endl;return 0;}}template <class T>bool LinkStack<T>::IsEmpty(){return (top->next==NULL);}template <class T>void LinkStack<T>::Clear(){StackNode<T> *p=NULL;while (!IsEmpty()){p=top->next;top->next=p->next;delete p;}}


double eval() 函数代码

double eval(){double number=0.0;//store the number in stringchar c;LinkStack<double> OprandStack;LinkStack<char> OperatorStack;OperatorStack.Push('#');while (!OperatorStack.IsEmpty()){//read the expression//expression evaluateif (cin.peek()>='0' && cin.peek()<='9'){//current char is oprandcin>>number;cout<<number;OprandStack.Push(number);continue;}//cin.peek() is not a numberif (IsOperator(cin.peek())){c=cin.get();cout<<c;}else c='#';//stdin stream is over, cin.peek()=='\n'char cmp;while (1){cmp=CompareOpt(OperatorStack.GetTop(),c);if (cmp=='<'){OperatorStack.Push(c);break;}if (cmp=='='){OperatorStack.Pop();break;}//'>' casedouble a,b;char opt;b=OprandStack.Pop();a=OprandStack.Pop();opt=OperatorStack.Pop();OprandStack.Push(Operate(a,opt,b));}}return (OprandStack.GetTop());}


支撑函数代码:

//returns true when c is in the set://^ * / + - ( ) #bool IsOperator(char c){return (c=='^' || c=='*' || c=='/' || c=='+' ||c=='-' || c=='(' || c==')' || c=='#');}char CompareOpt(char opt1,char opt2){//priority table//row 0 is the operator//row 1-8 is the relationshipchar priority[9][9]={{' ','^','*','/','+','-','(',')','#'},{'^','>','>','>','>','>','<','>','>'},{'*','<','>','>','>','>','<','>','>'},{'/','<','>','>','>','>','<','>','>'},{'+','<','<','<','>','>','<','>','>'},{'-','<','<','<','>','>','<','>','>'},{'(','<','<','<','<','<','<','=',' '},{')','>','>','>','>','>',' ','>','>'},{'#','<','<','<','<','<','<',' ','='}};int row=0,col=0;for (int i=0;i<9;i++){if (opt2==priority[0][i]) col=i;if (opt1==priority[i][0]) row=i;}return priority[row][col];}double Operate(double a,char opt,double b){double result=0.0;int i=0;switch (opt){case '^':i=int(b);result=1;while (i--){result*=a;}break;case '*':result=a*b;break;case '/':result=a/b;break;case '+':result=a+b;break;case '-':result=a-b;break;default:result=a;break;}return result;}


 

主函数代码:

#include "InfixExpression.h"int main(){double result=0.0;while(1){cout<<"Input expression:('@' for exit)"<<endl;if (cin.peek()=='@'){cout<<"Thanks for testing."<<endl;break;}result=eval();cout<<" = "<<result<<endl;cin.get();}return 0;}