二叉树计算中缀表达式

看到《数据结构:思想与实现》这本书里5.3的程序(给出的程序是有问题的),代码敲到VS中,发现右闭括号不能起到作用,例如:输入(3+5)*7,输出则是38,右闭括号没有起到作用。自己调了很久,终于修改对了,下面是正确的代码:

#include 
using namespace std;
class calc
{
    enum Type {DATA, ADD, SUB, MULTI, DIV, OPAREN, CPAREN, EOL};
    struct node
    {
        Type type;
        int data;
        node *lchild, *rchild;
        node(Type t, int d=0, node *lc=NULL, node *rc=NULL)
        {
            type=t; data=d; lchild=lc; rchild=rc;
        }
    };
    node *root;
    node *create(char * &s);
    Type getToken (char * &s, int &value);
    int result (node *t);	
    public:	
	void preOrder(node* &t);
    calc (char *s) {root=create(s);}
    int result() {if (root==NULL) return 0;return result(root);}	
};

calc::node *calc::create(char * &s)
{
    node *p, *root=NULL;
    Type returnType,flag;
    int value;
    while (*s)
    {
        returnType=getToken(s,value);		
        switch (returnType)
        {
            case DATA:
            case OPAREN:
                if (returnType == DATA) p=new node(DATA,value);
                else p=create(s);
                if (root==NULL) root=p;
                else if (root->rchild==NULL) root->rchild=p;
                     else root->rchild->rchild=p;
                break;
            case CPAREN: flag=CPAREN;break;
            case EOL: return root;
            case ADD:
            case SUB:
                root=new node(returnType,0,root);//这句话非常秒,如果扫描到加减、结束,那么就新建一个结点作为根结点并且其左指针指向上一次的结点
                break;
            case MULTI:
            case DIV:
				/*此时比较扫描到的运算符和根结点的运算符的关系:
				1.是同级的运算符,遵循从左向右的原则,将此时的运算符作为新的根结点;也就是遇同级每次都是把最新一次的放到根节点中
				2.是运算数,说明这个运算数是要用于现在这个运算符的,而且还是那句话,根结点里存的肯定不是运算数;*/				
                if (root->type==DATA || root->type==MULTI || root->type==DIV||flag==CPAREN) root=new node(returnType,0,root);
				//这个else说明是一个低一些的运算符,新建一个结点,使原来root的右指针指向它,并且初始化它的左指针为等于原来的右指针
                else root->rchild=new node(returnType,0,root->rchild);
        }
    }
    return root;
}

calc::Type calc::getToken(char *&s, int &data)
{
    char type;
    while (*s==' ') ++s;
    if (*s>='0' && *s<='9')
    {
        data=0;
        while (*s>='0' && *s<='9') {data=data*10+ *s-'0'; ++s;}
        return DATA;
    }
    if (*s == '\0') return EOL;
    type =*s; ++s;//程序到这一步,就说明这个字符既不是数字也不是空字符,而且下次的扫描的是s指向的字符串中的下一个字符。
    switch(type)
    {
        case '+':return ADD;
        case '-':return SUB;
        case '*':return MULTI;
        case '/':return DIV;
        case '(':return OPAREN;
        case ')':return CPAREN;
        default: return EOL;
    }
}
//根结点一定是运算符,且是最后一个加入计算的运算符
int calc::result(node *t)
{
    int num1,num2;
	if (t->type == DATA) {cout<<"**"<data<data;}
    num1=result(t->lchild);
	cout<<"num1= "<rchild);
	cout<<"num2= "<type)
    {
        case ADD:t->data=num1+num2;break;
        case SUB:t->data=num1-num2;break;
        case MULTI: t->data=num1*num2;break;
        case DIV:t->data=num1/num2;break;
    }
	cout<<"/*/"<data<data;
}
int main()
{   
    calc exp("(3+5)*7/(8-4)");
    cout<


 
  修改的地方是当扫描到“)”时,给出一个标志位flag记录此时的type,当下一个符号比括号里的表达式的运算符高级时,进行创建新的根结点而不是将这个结点作为原来根结点的子结点。 
  

显示结果如下:

二叉树计算中缀表达式_第1张图片

你可能感兴趣的:(数据结构与算法)