二叉树思想实现的计算器

实现一个简单的计算器。通过键盘输入一个包含圆括号、加减乘除等符号组成的算术表达式字符串,输出该算术表达式的值。要求:
(1)系统至少能实现加、减、乘、除等运算;
(2)利用二叉树算法思想求解表达式的值,先构造由表达式构成的二叉树,然后再利用通过对二叉树进行后序遍历求解算术表达式的值。

#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <cmath>
using namespace std;



bool IsOperator(string mystring)   //判断字符串是否是运算符
{
    if(mystring == "-"||mystring == "+"||mystring == "*"||mystring == "/")
        return true;
    else
        return false;
}

bool IsOperator(char ops)  //判断一个字符是否是运算符
{
    if(ops == '+'||ops== '-'||ops== '*'||ops== '/'||ops=='('||ops==')')
        return true;
    else
        return false;
}

bool IsOperand(char ch)   //判断是否是数字
{
    if (((ch>='0')&&(ch<='9'))||(ch=='.'))
        return true;
    else
        return false;
}

bool judge(string exp)   //判断输入是否正确
{
    char check;
    int error=0,lb=0,rb=0,numofoperand=0,numofoperator=0;
    for(int m=0;m<exp.size();m++)
    {
        check=exp[m];
        if(IsOperand(check))
        {
            if(check=='.')//判断浮点型数据是否正确
            {
                if(!(exp[m-1]>='0'&&exp[m-1]<='9')&&(exp[m+1]>='0'&&exp[m+1]<='9'))
                {
                    error++;
                    cout<<"浮点型数据输入有误!!!"<<endl;
                }
            }
            numofoperand++;
        }
        else if(IsOperator(check))
        {
            if(check==')')
            {
                rb++;
                if(rb>lb)
                {
                    error++;
                    cout<<"右括号不可能大于左括号!!!"<<endl;
                }
                if(IsOperator(exp[m+1])&&(exp[m+1]=='+'||exp[m+1]=='-'||exp[m+1]=='*'||exp[m+1]=='/'||exp[m+1]==')'))
                {
                    numofoperator++;
                    m++;
                    if(exp[m]==')')
                        rb++;
                }
                else if(IsOperator(exp[m+1])||IsOperand(exp[m+1]))
                {
                    error++;
                    cout<<"右括号后不可能直接跟数据或左括号!!!"<<endl;
                }     
            }
            else if(check=='(')
            {
                lb++;
                if(IsOperator(exp[m+1])&&exp[m+1]=='('||exp[m+1]=='-')//左括号右边只能是数字或者"-"号
                {
                    m++;
                    m++;
                    lb++;
                }
                else if(IsOperator(exp[m+1]))
                {
                    error++;
                    cout<<"左括号后运算符只能跟左括号!!!"<<endl;
                }
            }
            else
            {     
                numofoperator++;
                if(IsOperator(exp[m+1])&&exp[m+1]=='(')
                {
                    m++;
                    lb++;

                }
                else if(IsOperator(exp[m+1]))
                {
                    error++;
                    cout<<"非括号的运算符不能直接接非括号运算符!!!"<<endl;
                }
            }
        }
        else
        {
            error++;
            cout<<check<<"为非法字符!!!"<<endl;
        }
    }
    if((error==0)&&(lb==rb)&&(numofoperand!=0)&&(numofoperator!=0))
        return true;
    else
        return false;
}
bool   addition(char   OperatorA,char   OperatorB)         //A和B的优先级相同时返回TRUE.   
{   
    if(OperatorA==OperatorB||(OperatorA=='*'&&OperatorB=='/')||(OperatorA=='/'&&OperatorB=='*')||(OperatorA=='+'&&OperatorB=='-')||(OperatorA=='-'&&OperatorB=='+'))   
        return   true;   
    else
        return   false;   
}   

bool TakesPrecedence(char OperatorA,char OperatorB)  //按照优先级用if从最优至最后从上至下排列,从而达到比较A与B的优先级
{
    if(OperatorA=='(')
        return false;
    else if(OperatorB=='(')
        return false;
    else if(OperatorB==')')
        return true;
    else   if(addition(OperatorA,OperatorB))  
        return false;
    else if((OperatorA=='*')||(OperatorA=='/'))
        return true;
    else if((OperatorB=='*')||(OperatorB=='/'))
        return false;
    else   if((OperatorA=='+')||(OperatorA=='-'))   
        return   true;
    else
        return true;
}

//****************************************************************************//

class BinNode{
public:
    string data;
    BinNode *left_child;
    BinNode *right_child;
    BinNode(string k)    //构造函数
    {
        data=k;
        left_child=NULL;
        right_child=NULL;
    }
};



class binarytree//树的类
{
public:
    BinNode *root;         //根节点
    binarytree(void){root=NULL;}   //构造函数
    void print(void){print(root);}
    void print(BinNode *p)
    {
        if(p!=NULL)
        {
            print(p->left_child);
            print(p->right_child);
            cout<<p->data<<" ";
        }
    }
    void evaluate(void){evaluate(root);}
    bool evaluate(BinNode *prt)  //计算二叉树一个节点
    {
        if(IsOperator(prt->data)&&!IsOperator(prt->left_child->data)&&!IsOperator(prt->right_child->data))//计算二叉树结点的值并存入新的二叉树结点
        {
            float num=0;
            float num1=atof(prt->left_child->data.c_str());
            float num2=atof(prt->right_child->data.c_str());

            if(prt->data=="+")
                num=num1+num2;
            else if(prt->data=="-")
                num=num1-num2;
            else if(prt->data=="*")
                num=num1*num2;
            else if(prt->data=="/")
            {
                if(num2==0.0)
                {
                    cout<<"除数为零!!!运算出错";
                    return 0;
                }
                else
                    num=num1/num2;
            }
            
            stringstream bob;
            bob<<num;
            string suzzy(bob.str());
            prt->data=suzzy;
            prt->left_child=NULL;
            prt->right_child=NULL;
        }
        else if(prt->left_child==NULL&&prt->right_child==NULL);
        else
        {
            evaluate(prt->left_child);
            evaluate(prt->right_child);
            evaluate(prt);
        }
        return 1;
    }
    void clear_help(void)
    {
        clear_help(root);
    }
    void clear_help(BinNode *rt)
    {
        if(rt!=NULL)
        {
            clear_help(rt->left_child);
            clear_help(rt->right_child);
            delete rt;
        }
    }
};

BinNode *build_node(string x)//创建一个临时结点
{
    BinNode *new_node;
    new_node=new BinNode(x);
    return (new_node);
}

void copy(BinNode *&r1,BinNode* r2)//这里将单个的子树连接起来
{
    if(r2==NULL)
        r1=NULL;
    else
    {
        r1=build_node(r2->data);
        copy(r1->left_child,r2->left_child);
        copy(r1->right_child,r2->right_child);
    }
}
//*******************************************************************************************

int main()
{
    binarytree etree;//创建树
    stack<binarytree> NodeStack;//创建栈
    stack<char> OpStack;
    string exp;//声明字符串
    char choice='y';//choice为选择是否继续运行程序的判断
    char c;//为下面创建二叉树进行取字符
    while(choice=='y'||choice=='Y')
    {
        cout<<"请输入一个有效的表达式:"<<endl;
        getline(cin,exp);
        cout<<"     "<<endl<<"-----------------------------"<<endl;
        
        if(judge(exp))//如果判断出表达式没有错误,则进行创建二叉树并计算
        {
            cout<<"表达式格式正确"<<endl;
            for(int i=0;i<exp.size();i++)
            {
                c=exp[i];
                if(i==0 && c=='-') //若开始为负,则把零压入运算数栈,把'-'压入运算符栈
                {   
                    binarytree   temp;   
                    temp.root=build_node("0");  
                    NodeStack.push(temp);
                    OpStack.push('-');
                }
                else
                    if(IsOperand(c))//若是操作数,则判断下一位是不是操作数,并且将整个数据创建一个子树并压栈
                    {
                        string tempstring="";
                        tempstring=tempstring+c;
                        while(i+1<exp.size()&&IsOperand(exp[i+1]))   //当当前位置的下一位也是操作数时,将整个数字放在一个临时数据串中
                        {   
                            tempstring+=exp[++i];   
                        }
                        binarytree temp;//为这个数据创建一个子树
                        temp.root=build_node(tempstring);
                        NodeStack.push(temp);//将子树的根节点指针压栈
                    }
                    else if(c=='+'||c=='-'||c=='/'||c=='*')//如果是操作符
                    {
                        if(OpStack.empty())//如果栈空,则直接压栈
                            OpStack.push(c);
                        else if(OpStack.top()=='(')//如果栈顶是左括号,则压栈
                            OpStack.push(c);
                        else if(TakesPrecedence(c,OpStack.top()))//判断栈顶字符和当前字符的优先级,当c优先级高或者个优先级相同时,将c压栈
                            OpStack.push(c);
                        else//其他普通情况
                        {   
                            while(!OpStack.empty()&&(TakesPrecedence(OpStack.top(),c)||addition(OpStack.top(),c)))//这里将在一般情况下,对已经压栈的操作数和操作符进行创建子树处理,并将当前字符压栈
                            {
                                binarytree temp_tree;
                                string thisstring="";
                                thisstring=thisstring+OpStack.top();//取栈顶进行计算字符串
                                OpStack.pop();
                                etree.root=build_node(thisstring);//当前树的根为栈顶计算出的字符串
                                copy(temp_tree.root,NodeStack.top().root);//子树的根节点放在临时树结点上
                                NodeStack.pop();
                                etree.root->right_child=temp_tree.root;//将临时结点放入新建子树的右孩子结点上,可以将个子树连接起来
                                temp_tree.root=NULL;//置空临时树结点
                                copy(temp_tree.root,NodeStack.top().root);//重复上面的步骤连接左孩子
                                etree.root->left_child=temp_tree.root;
                                NodeStack.pop();
                                temp_tree.root=NULL;
                                copy(temp_tree.root,etree.root);
                                NodeStack.push(temp_tree);
                                etree.root=NULL;
                            }
                            OpStack.push(c);
                        }
                    }
                    else if(c=='(')    //若中间遇到括号,则判断下一位是否为'-'
                    {
                        OpStack.push(c);
                        if(exp[i+1]=='-')
                        {
                            binarytree   temp;
                            temp.root=build_node("0");
                            NodeStack.push(temp);
                            OpStack.push('-');
                            i++;
                        }
                    }   
                    else if(c==')')//如果遇到右括号,则创建子树,直到与左括号匹配成功,这里和前一步骤的操作基本相同
                    {
                        while(OpStack.top()!='(')
                        {
                            binarytree temp_tree;
                            string thisstring="";
                            thisstring=thisstring+OpStack.top();
                            OpStack.pop();
                            etree.root=build_node(thisstring);
                            copy(temp_tree.root,NodeStack.top().root);
                            NodeStack.pop();
                            etree.root->right_child=temp_tree.root;
                            temp_tree.root=NULL;
                            copy(temp_tree.root,NodeStack.top().root);
                            etree.root->left_child=temp_tree.root;
                            NodeStack.pop();
                            temp_tree.root=NULL;
                            copy(temp_tree.root,etree.root);
                            NodeStack.push(temp_tree);   
                            etree.root=NULL;
                        }
                        OpStack.pop();
                    }
            }
            while(!OpStack.empty())//如果栈非空,则继续进行出栈、判断、计算,直到栈空,栈中的结果为最终的计算结果
            {
                binarytree temp_tree;
                string thisstring="";
                thisstring=thisstring+OpStack.top();
                OpStack.pop();
                etree.root=build_node(thisstring);
                copy(temp_tree.root,NodeStack.top().root);
                NodeStack.pop();
                etree.root->right_child=temp_tree.root;
                temp_tree.root=NULL;
                copy(temp_tree.root,NodeStack.top().root);
                etree.root->left_child=temp_tree.root;
                NodeStack.pop();
                temp_tree.root=NULL;
                copy(temp_tree.root,etree.root);
                NodeStack.push(temp_tree);
                if(!OpStack.empty())
                    etree.root=NULL;
            }
            //cout<<"Postfix traversal:";
            //etree.print();
            //cout<<endl;
            etree.evaluate();
            cout<<"表达式计算结果:"<<exp<<"="<<etree.root->data<<endl;
            cout<<"------------------------------------------------"<<endl;
            cout<<endl<<"是否继续计算下一个表达式<y/n>:";
            cin>>choice;
            getchar();
        }
        else
        {
            cout<<"**************************"<<endl;
            cout<<"错误:表达式有误"<<endl;
            cout<<endl<<"是否继续计算下一个表达式<y/n>:";
            cin>>choice;
            getchar();
        }
    }
    return 0;
}
  • 10
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值