将逆波兰式转换成波兰式表达式

将逆波兰式转换成波兰式表达式
    这是严蔚敏《数据结构》配套习题册上的题目:将逆波兰式转换成波兰式,并提示错误(作为简化,只处理"+-*/"和0~9的数字)。
    例如:"123*-"转换成波兰式为"-1*23"
    逆波兰式"123*-"的表达式树如下:
    所以这个转换过程就是:已知一个二叉树的后根遍历序列,求先根遍历序列。
    我的算法是根据后根遍历的序列构造一个表达式树,进而先根遍历此树获得波兰式表达式。
    定义了两个结构体:
struct  Exp{
    
char   op;
    Item  lhs;
    Item  rhs;
    Exp(){};
    Exp(
char  _op, Item _lhs, Item _rhs):op(_op), lhs(_lhs), rhs(_rhs){ }
    Exp(
const  Exp &  e):op(e.op), lhs(e.lhs), rhs(e.rhs) { }
};

表示一个表达式,也是表达式树上的一个子树。
struct  Item{
    
char   number;
    shared_ptr
< Exp >  pExp;
    
bool  isNumber;
    
explicit  Item():isNumber( true ), number( ' 0 ' ), pExp(){    }
    Item(
const  Item &  i):number(i.number), pExp(i.pExp), isNumber(i.isNumber){ }
};


表示一个节点,它可以是一个数字,或者一个表达式(pExp这里我使用的是boost库的智能指针shared_ptr,所以编译的话,需要先安装boost库)。
运行的结果如图:

*输入时,以'e'表示输入结束。
完整的代码和可执行文件点击这里下载。权当抛砖引玉了,希望有更好算法的同学赐教。

完整的代码:

#include <stack>
#include 
<algorithm>
#include 
<string>
#include 
<iostream>
#include 
<boost/shared_ptr.hpp>
using namespace std;
using boost::shared_ptr;

struct Exp;
struct Item{
    
char  number;
    shared_ptr
<Exp> pExp;
    
bool isNumber;
    
explicit Item():isNumber(true), number('0'), pExp(){    }
    Item(
const Item& i):number(i.number), pExp(i.pExp), isNumber(i.isNumber){ }
}
;

struct Exp{
    
char  op;
    Item  lhs;
    Item  rhs;
    Exp()
{};
    Exp(
char _op, Item _lhs, Item _rhs):op(_op), lhs(_lhs), rhs(_rhs){ }
    Exp(
const Exp& e):op(e.op), lhs(e.lhs), rhs(e.rhs) { }
}
;

class Error{
    
string info;
public:
    Error(
string _info):info(_info){ }
    Error():info(
""){ }
    
string what(){return info;}   
}
;

void printPorland(Exp& exp){
    cout 
<< exp.op ;
    
if(exp.lhs.isNumber)  cout << exp.lhs.number;
    
else printPorland(*exp.lhs.pExp);
    
if(exp.rhs.isNumber)  cout << exp.rhs.number;
    
else printPorland(*exp.rhs.pExp);
    
return;
}


int main()
{
    stack
<Item>  ExpStack;
    
char tmpChar;
    Item tmpItem;
    Item tmpLhs;
    Item tmpRhs;
    
string  numbers = "0123456789";
    
string  operators = "+-*/";

    cout
<<"Input the Express(输入 'e'标识结束):";
    
do{
    
try{
        
while(cin>>tmpChar){
            
if(tmpChar == 'e'break;  //e为结束符
            else if(find(numbers.begin(), numbers.end(),  //是一个数字
                    tmpChar)!=numbers.end()){
                tmpItem.isNumber 
= true;
                tmpItem.number   
= tmpChar;
                ExpStack.push(tmpItem);
//数字入栈

            }
else if(find(operators.begin(), operators.end(), //是一个操作符
                    tmpChar)!=operators.end()){
                
//操作符每次要对应两个被操作数,否则语法错误
                if(ExpStack.size()<2throw Error("Syntactic Error!"); 

                
//操作符两边的元素出栈
                tmpRhs = ExpStack.top();
                ExpStack.pop();
                tmpLhs 
= ExpStack.top();
                ExpStack.pop();

                tmpItem.isNumber 
= false;   //非数字,是一个表达式
                tmpItem.pExp = shared_ptr<Exp>(new Exp(tmpChar, tmpLhs, tmpRhs)); 

                ExpStack.push(tmpItem);     
//表达式入栈
                           
            }
else {  // 未知字符
                throw  Error("Unknow Character!");
            }

        }


        
if(ExpStack.size()!=1throw Error("Syntactic Error!");

        tmpItem 
= ExpStack.top();
        ExpStack.pop();

        
if(tmpItem.isNumber) cout << tmpItem.number <<endl;
        
else printPorland(*tmpItem.pExp);
        cout 
<< endl;

    }
catch(Error& e){
        cout 
<< e.what() << endl;
        getline(cin, 
string());        //跳过错误的当前行
    }


        cout 
<< "Try again?(y/n)" << endl;
        cin 
>> tmpChar;
    }
while(tmpChar == 'y' || tmpChar == 'Y');
    
    
return 0;
}

你可能感兴趣的:(将逆波兰式转换成波兰式表达式)