数据结构与算法:算术表达式的语义二叉树

一个算术表达式的计算语义可以用二叉树唯一的表示出来。假设算术表达式的语义二叉树已经给出,请编码实现算术表达式的中缀形式(保持计算语义)的输出,并计算出该表达式的值。
要求:
1)使用二叉树的完全前序序列建立表达式的语义二叉树,空子树用符号@表示;
2)算术运算符包括:+, -, * , / ; 运算量只考虑单数字字符(1位整数)
3 ) 输出时用括号该表优先级;
4) 如果结果有小数,小数点后保留5位;
提示:
1)递归执行下列步骤即可求值:先分别求出左子树和右子树表示的子表达式的值,最后根据根结点的运算符的要求,计算出表达式的最后结果。
2)二叉树的中序遍历序列与原算术表达式基本相同,但是需要将中序序列加上括号,即当根结点运算符优先级高于左子树(或右子树)根结点运算符时,就需要加括号。
例如:
输入:*

2@@-3@@1@@

输出:

2*(3-1)=4

输入

-*-7@@5@@+/4@@6@@-3@@*5@@2@@+/7@@3@@9@@

输出

(7-5)*(4/6+3-5*2)-(7/3+9)=-24

输入

-*-5@@7@@+/4@@6@@-3@@*5@@2@@+/7@@3@@9@@

输出

(5-7)*(4/6+3-5*2)-(7/3+9)=1.33333
#include<bits/stdc++.h>
using namespace std;
string eqn="";//最终生成带括号的中缀表达式
int priority[130]={
    
    0};
void getPriority()//栈运算的优先级
{
    
    
    priority['+']=1;
    priority['-']=1;
    priority['*']=2;
    priority['/']=2;
}
int cmp(char theta1,char theta2)//栈运算的优先级比较
{
    
    
    return priority[theta1]-priority[theta2];
}
bool cmp(char c1,char c2,int l_or_r)//二叉树加括号的优先级比较
{
    
    
    if(l_or_r==1&&c2=='-')return false;
    else if((c1=='+'||c1=='-')&&(c2=='*'||c2=='/'||c2=='-'))return true;
    else if((c1=='*'&&c2=='/')||(c1=='/'&&c2=='/'))return true;
    else return false;
}
template<class T>//模板类
class Stack//栈
{
    
    
private:
    T a[105];
    int up,down;
public:
    Stack(){
    
    up=0;down=0;}
    void Push(T x){
    
    a[up++]=x;}
    void Pop(){
    
    up--;}
    T Top(){
    
    return a[up-1];}
    int Size(){
    
    return up-down;}
    bool Empty(){
    
    return up==down?true:false;}
};
typedef struct node//结点类
{
    
    
    char data;
    struct node*leftchild,*rightchild;
}Node;
class BinTree//二叉树类
{
    
    
public:
    Node*root;
    void create(Node*&t);//建立二叉树
    void travel(Node*subtree,char c,int l_or_r);//遍历二叉树并获取带括号的中缀表达式
};
void BinTree::create(Node*&t)
{
    
    
    char ch;
    cin>>ch;
    if(ch=='@') t=NULL;
    else
    {
    
    
        t=new Node;
        t->data=ch;
        create(t->leftchild);
        create(t->rightchild);
    }
}
void BinTree::travel(Node*subtree,char c,int l_or_r)
{
    
    
    if(subtree!=NULL)
    {
    
    
        if(!isdigit(subtree->data)&&cmp(subtree->data,c,l_or_r))eqn+="(";
        travel(subtree->leftchild,subtree->data,1);
        eqn+=subtree->data;
        travel(subtree->rightchild,subtree->data,0);
        if(!isdigit(subtree->data)&&cmp(subtree->data,c,l_or_r))eqn+=")";
    }
}
Stack<double>num;
Stack<char>op;
double cal(double num1,double num2,char op)//4种运算
{
    
    
    if(op=='+')return num1+num2;
    else if(op=='-')return num1-num2;
    else if(op=='*')return num1*num2;
    else if(op=='/')return num1/num2;
}
int main()
{
    
    
    BinTree btree;
    getPriority();
    btree.create(btree.root);
    btree.travel(btree.root,' ',2);
    int i;
    double a,b;
    for(i=0;i<=eqn.length()-1;i++)
    {
    
    
        if(eqn[i]>='0'&&eqn[i]<='9')num.Push(eqn[i]-'0');
        else if(eqn[i]=='+'||eqn[i]=='-'||eqn[i]=='*'||eqn[i]=='/'||eqn[i]=='('||eqn[i]==')')
        {
    
    
            if(op.Empty()||eqn[i]=='('||op.Top()=='('||cmp(op.Top(),eqn[i])<0)op.Push(eqn[i]);
            else if(eqn[i]==')')
            {
    
    
                while(op.Top()!='(')
                {
    
    
                    a=num.Top();
                    num.Pop();
                    b=num.Top();
                    num.Pop();
                    num.Push(cal(b,a,op.Top()));
                    op.Pop();
                }
                op.Pop();
            }
            else if(cmp(op.Top(),eqn[i])>=0)
            {
    
    
                while(cmp(op.Top(),eqn[i])>=0)
                {
    
    
                    a=num.Top();
                    num.Pop();
                    b=num.Top();
                    num.Pop();
                    num.Push(cal(b,a,op.Top()));
                    op.Pop();
                    if(op.Empty())break;
                }
                op.Push(eqn[i]);
            }
        }
    }
    while(!op.Empty())
    {
    
    
        a=num.Top();
        num.Pop();
        b=num.Top();
        num.Pop();
        num.Push(cal(b,a,op.Top()));
        op.Pop();
    }
    cout<<eqn;
    printf("=");
    if(abs(num.Top())-(int)abs((num.Top()))<=1e-7)printf("%d",(int)num.Top());
    else printf("%.5f",num.Top());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/upc122/article/details/105941276