中缀表达式(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)
注意这些比较符左边为 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;}
- 中缀表达式(Infix Notation)的求解,只考虑双目运算符情况
- 求解中缀表达式...
- [python]将中缀表达式(infix)转换为后缀表达式(postfix)
- 双目运算符的重载
- 双目运算符的重载
- 2. evaluate-reverse-polish-notation 后缀表达式的求解
- 用栈和队列实现中缀表达式的求解
- 中缀表达式转前缀表达式的简便运算
- 中缀表达式的计算(只包含四则运算与括号)
- 双目运算符+=的重载
- 双目运算符重载
- 双目运算符&&和||
- 重载双目运算符
- 双目运算符重载
- 双目运算符重载
- js双目运算符"&&"和"||"的运算方向
- 【数据结构与算法基础】栈及其应用后缀、中缀表达式 / Stack and postfix/infix expression
- 字符串四则运算表达式的求解(中缀表达式实现,模拟笔算的方法)
- JSP c:ForEach
- 工作点滴(四)Linux下合并二进制文件
- IPC介绍
- 在 Android 上使用 XML
- 多线程:4种定时器
- 中缀表达式(Infix Notation)的求解,只考虑双目运算符情况
- Android中抓取手机视频流数据。
- Graphics->Clipping Canvas提供了ClipPath, ClipRect, ClipRegion 等方法来裁剪,通过Path, Rect ,Region 的不同组合,Androi
- MES,ShopFloor
- iPhone4S价格走势平稳 现价5999值得买
- 不要被N!吓到--《编程之美》例题
- Ipad开发加载图片的几种方式
- 去掉.svn文件夹
- 设计模式——单例(Singleton)模式