后缀表达式可以简化计算机对表达式的求值。
中缀表达式:A+B*C,转化为后缀表达式为:ABC*+。计算机求值时,依次读入并压栈,当读到运算符时,去除栈顶的两个元素,运算,并把运算结果入栈。
对于后缀表达式ABC*+的求值过程:
1.读取A, A入栈,栈中元素为A
2. 读取B,B入栈,栈中元素为AB
3. 读取C,C入栈,栈中元素为ABC
4. 读取*,C退栈,B退栈,对B和C执行乘法操作,设t=B*C,t入栈,栈中元素为At
5. 读取+,t退栈,A退栈,对A和t执行加法操作,栈中无元素,表达式的值为A+t,其中t为B*C
再看看有括号的表达式求值,A*(B+C)*D,其后缀表达式为ABC+*D*
对于后缀表达式ABC+*D*的求值过程:
1. 读取A,A入栈,栈中元素为A
2. 读取B,B入栈,栈中元素为AB
3. 读取C,C入栈,栈中元素为ABC
4. 读取+,C退栈,B退栈,执行加法运算,设p=B+C,p入栈,栈中元素为Ap
5. 读取* ,p退栈,A退栈,执行乘法运算,设q=A*p,q入栈,栈中元素为q
6. 读取D,D入栈,栈中元素为qD
7.读取* ,D退栈,q退栈,执行乘法运算,表达式的值为q*D。
可以看出,将中缀表达式转化为后缀表达式,可以去除括号并且产生不具二义性的可用于计算机计算的表达式。那么,关键是如用程序将中缀表达式转化为后缀表达式。
思路:
1.后缀表达式与中缀表达式中的操作数的顺序不变,只是去除了括号和改变了操作符的位置。
2.需要借助一个栈,来操作运算符。
用代码来说明:
myStack.h
#pragma once #include <memory.h> template<class T> class myStack { public: myStack(int capacity=10); ~myStack(void); void push(T e); T pop(); bool isEmpty(); T copyTop(); private: T* array; int capacity; int top; void addSize(); }; template<class T> myStack<T>::myStack(int capacity/*=10*/) { array =new T[capacity]; //top=-1 说明为空 top=-1; this->capacity=capacity; } template<class T> void myStack<T>::push(T e) { if(top+1==capacity) addSize(); array[++top]=e; } template<class T> T myStack<T>::pop() { return array[top--]; } template<class T> myStack<T>::~myStack(void) { delete[] array; } template<class T> void myStack<T>::addSize() { T* temp=new T[capacity+10]; memcpy(temp,array,sizeof(T)*(capacity+10)); delete[] array; array=temp; capacity+=10; } template<class T> bool myStack<T>::isEmpty() { return top==-1; } template<class T> T myStack<T>::copyTop() { return array[top]; }infix2postfix.h
#pragma once #include "myStack.h" class infix2postfix { public: infix2postfix(char *str); ~infix2postfix(void); //打印后缀表达式 void printPostfix(); private: //符号进栈,出栈操作 myStack<char> s; char *src; char *result; int index; //获取除去了之后的字符串长度,用以申请result空间 int getValidLength(); //获取后缀表达式 void getPostfix(); //处理括号 void processBrackets(char c); //处理运算符 void processOperator(char c); //处理操作数 void processOperand(char c); };infix2postfix.cpp
#include "infix2postfix.h" #include <string.h> #include <iostream> using namespace std; infix2postfix::infix2postfix(char*str) { index=0; src=new char[strlen(str)+1]; strcpy(src,str); result=new char[getValidLength()+1]; result[getValidLength()]=0; getPostfix(); } infix2postfix::~infix2postfix(void) { delete[]src; delete[]result; } //获取除去了之后的字符串长度,用以申请result空间 int infix2postfix::getValidLength() { char *p=src; int len=0; while(*p++!=0) { if(*p!='(' && *p!=')') len++; } return len; } //打印后缀表达式 void infix2postfix::printPostfix() { cout<<"中缀:"<<src<<endl; cout<<"后缀:"<<result<<endl<<endl; } //获取后缀表达式 void infix2postfix::getPostfix() { char*p=src; while(*p!=0) { if(*p=='(' || *p==')') processBrackets(*p); else if(*p=='+' || *p=='-' || *p=='*' || *p=='/') processOperator(*p); else processOperand(*p); p++; } while(!s.isEmpty()) result[index++]=s.pop(); } //处理括号 void infix2postfix::processBrackets(char c) { if(c=='(') s.push(c); else { char e; while( (e=s.pop())!='(' ) result[index++]=e; } } /* **处理运算符 **如果是'+'或'-',把运算符栈s依次退栈,直到遇见'(',并存入后缀表达式 **如果是'*'或'/',把运算符栈s依次退栈,直到遇见'(','+','-',并存入后缀表达式 */ void infix2postfix::processOperator(char c) { bool flag=false; if(c=='+' || c=='-') flag=true; while(!s.isEmpty()) { if(s.copyTop()!='(' && (flag|| (s.copyTop()!='+' && s.copyTop()!='-') )) result[index++]=s.pop(); else break; } s.push(c); } //处理操作数,直接存入后缀表达式 void infix2postfix::processOperand(char c) { result[index++]=c; }
#include <iostream> #include "infix2postfix.h" int main() { infix2postfix i2p("A*B+c"); i2p.printPostfix(); infix2postfix i2p2("A/B-C+D*E-A*C"); i2p2.printPostfix(); infix2postfix i2p3("a*(b+c)*d"); i2p3.printPostfix(); }