广工 数据结构 表达式类型求值(中)

表达式的基本操作

Status InitBiTree(BiTree &T){

  //操作结果:初始化为空树

  T=NULL;

  return OK;   

}

Status InitStack(SqStack &S)  { 

    S.base = (SElemType *) malloc (STACK_INIT_SIZE * sizeof(SElemType)); 

    if(!S.base) 

        exit(OVERFLOW); 

    S.top = S.base; 

    S.stacksize = STACK_INIT_SIZE; 

    return OK; 

}    

Status Push(SqStack &S, SElemType e)  {   //元素e压栈    

    if((S.top - S.base >= S.stacksize)) {     

              //栈满,追加存储空间   

        S.base = (SElemType *) realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType)); 

        if(!S.base)                                      //存储分配失败   

            exit(OVERFLOW); 

        S.top = S.base + S.stacksize; 

        S.stacksize += STACKINCREMENT; 

    } 

    *S.top++ = e; 

    return OK; 

}  

Status Pop(SqStack &S, SElemType &e)  { 

    if(S.base == S.top) 

       return ERROR; 

    e = *--S.top; 

    return OK; 

Status GetTop(SqStack S, SElemType &e)  {

    if(S.top > S. base)   { 

        e = *(S.top - 1); 

        return OK; 

    } 

    return ERROR; 

//清空栈

Status ClearStack(SqStack &S){

       S.top = S.base;

       S.stacksize = STACK_INIT_SIZE;

       return OK;

}

//判栈空, 空的话返回OK

Status StackEmpty(SqStack S){

   

    if (S.top == S.base)

              return OK;

    else

              return ERROR;

}

//初始化空队列

Status InitQueue(LinkQueue &Q) {  

   Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));

   //if (!Q.front) exit (OVERFLOW);//存储分配失败

   Q.front->next = NULL;

   return OK;

}

//入队列

Status EnQueue(LinkQueue &Q, QElemType e) {   

    QueuePtr p;

    p = (QueuePtr)malloc(sizeof(QNode));

    //if (!p) exit (OVERFLOW);   //存储分配失败

    p->data = e;   p->next = NULL;

    Q.rear->next = p;   

    Q.rear = p;

    return OK;

}

//出队列

Status DeQueue(LinkQueue &Q, QElemType &e) {

   QueuePtr p;

   if (Q.front == Q.rear)

      return ERROR;

   p = Q.front->next;

   e = p->data;

   Q.front->next = p->next;

   if (Q.rear == p) 

      Q.rear = Q.front;

   free (p);     

   return OK;

}

//判断输入的表达式是否为正确的后缀表达式

Status Judge(SqStack &S){

       BiTree T;

       InitBiTree(T);

       if(StackEmpty(S))

              return ERROR;

       else{

              Pop(S, T);

              if(StackEmpty(S)){                                              //如果栈为空,说明栈中只有一个元素,即是最终的那颗树

                     Push(S, T);                                                    //把正确结果的树入栈,以便后续使用                 

                     return OK;

        }else{                                                     //如果栈不为空,说明栈中还有许多结点或树,这将不是由正确的后缀表达式所构造出了的结果

                     return ERROR;         

        }

}

return OK;

}        

//创建二叉树

Status CreateBiTree(BiTree &T, TElemTag te){

       T = (BiTree)malloc(sizeof(BiTNode));

       T->data = te;

       T->lchild = NULL;

       T->rchild = NULL;

return OK;

}

//销毁二叉树

void Destory(BiTree &T) { 

       if(T)  {   

              Destory(T->lchild);   

              Destory(T->rchild);   

              free(T);    

              T = NULL; 

       }  

}

//若c为'0'创建数字叶子结点 ,否则创建字母叶子结点

Status CreatLeftNode(TElemTag &te, double d, int n, char c, SqStack &S, BiTree &T){            

 

       if(c == '0'){                              //整型

              te.tag = INT;

              te.n = n;

       }else if(c == '1'){                            //实型

              te.tag = DOU;

              te.num = d;

       }else if(d == 0.0){                          //字符型

        if(isdigit(c)){                                   //当变量为a1这种形式时,取最后一位'1', 此时当做整数处理

                     te.tag = INT;

                     te.n = c - '0';

              }else{                                                     //正常的单字母变量

                     te.tag = CHAR;

                     te.c = c;

              }

       }

       CreateBiTree(T, te);

       Push(S, T);                                   //入栈

       return OK;

}

//创建分支结点

Status CreatSwitchNode(TElemTag &te, char c, SqStack &S, BiTree &T){             

       SElemType ST1, ST2;

       te.tag = OPER;

       te.c = c;

       CreateBiTree(T, te);

       Pop(S, ST2);                             //叶子结点出栈,作为分支结点的左右孩子

       Pop(S, ST1);

       T->lchild = ST1;

       T->rchild = ST2;

       Push(S, T);                                   //入栈

       return OK;

}

//输入函数,用来创建二叉树的核心函数

void Input(SqStack &S, BiTree &T){

       TElemTag te;

       char a[6]={0}, in[81]={0};                    //in为接收键盘输入的字符数组,a为用来存放数字串的字符数组

       int len1, len2, j=0;

       int flag = 0, num1;

       double num;

       char c;

       getchar();                                                       //接收换行符,因为输入函数的缓冲区处理

       gets(in);

       len1 = strlen(in);

       while(1){                                                       //检查是否存在不规范字符

              for(int k=0; k

                     if(in[k]!=' ' && in[k]!='.' && !isalnum(in[k]) && !(in[k]=='+' || in[k]=='-' || in[k]=='*' || in[k]=='/' || in[k]=='^')){

                    

                            printf("对不起,你的输入有误,请重新输入!\n");

                            break;

                     }

              }

              if(k >= len1)                             //输入正确,跳出循环

                     break;

              else{

                     gets(in);

                     len1 = strlen(in);

              }

       }

       for(int i=0; i

              if((in[i]=='-' && isdigit(in[i+1])) || isdigit(in[i])){                     //负数字符串 和 正数字符串            

                     while(in[i]!=' '){                                                   //数字串

                            if(i == len1)                                                   //如果已经是最后一个字符就break

                                   break;

                            a[j++] = in[i++]; 

                     }

                     len2 = strlen(a);

                     for(int r=0; r

                            if(a[r] == '.'){

                                   flag = 1;

                                   break;

                            }

                     }

                     if(flag == 1){

                                                                     

                            num = atof(a);                                               //将字符串转化为浮点数   atof(a) 出自 #include 

                            CreatLeftNode(te, num, 0, '1', S, T);     //第4个参数为'1'说明要创建实数型数字叶子结点

                     }

                     else{                                                                     //转化为整数

                            num1 = atoi(a);                                              //atoi(a) 出自 #include 

                            CreatLeftNode(te, 0.1, num1, '0', S, T);       //第4个参数为'0'说明要创建整型数字叶子结点

                     }

                     for(int p=0; p

                            a[p] = 0;

              }else if(isalpha(in[i])){                    //字符变量,如果输入为字符串,则取串中最后一个字符为字符变量

                     while(in[i]!=' '){

                                   if(i == len1)                                                   //如果已经是最后一个字符就break

                                          break;

                                   c = in[i++];

                            }

                     CreatLeftNode(te, 0.0, 0, c, S, T);         //第二个参数为0.0说明要创建字母叶子结点

              }else if(in[i]=='+' || in[i]=='-' || in[i]=='*' || in[i]=='/' || in[i]=='^'){

                     c = in[i++];

                     CreatSwitchNode(te, c, S, T);               //创建操作符分支结点

 

              }else if(in[i] == ' '){

                     i++;

              }

       }

}

//中序遍历

void Inorder(BiTree t){

    if(t){

        Inorder(t->lchild);

              if(t->data.tag == INT)

                     printf("%d\t", t->data.n);

              else if(t->data.tag==CHAR || t->data.tag==OPER)

                     printf("%c\t", t->data.c);

              else if(t->data.tag == DOU)

                     printf("%lf\t", t->data.num);

        Inorder(t->rchild);

    }

}    

//前序遍历

void Perorder(BiTree t){

    if(t){

              if(t->data.tag == INT)

                     printf("%d\t", t->data.n);

              else if(t->data.tag==CHAR || t->data.tag==OPER)

                     printf("%c\t", t->data.c);

              else if(t->data.tag == DOU)

                     printf("%lf\t", t->data.num);

        Perorder(t->lchild);

        Perorder(t->rchild);

    }

}       

      

//求深度

int Depth(BiTree T){

       int l=0, r=0;

       if(T == NULL)

              return 0;

     l = Depth(T->lchild);

     r = Depth(T->rchild);

     if(l > r)

            return l+1;

     else

            return r+1;

}

//创建一个空结点的树,便于在入队列2时把所有结点(包括空结点)入队列

BiTree NullBiTree(){

     BiTree T;

     TElemTag te;

     te.tag = CHAR;

     te.c = '#';

     InitBiTree(T);

     CreateBiTree(T, te);

     return T;

//层次遍历二叉树

LinkQueue HierarchyBiTree(BiTree Root){

     LinkQueue Q1, Q2;                        // 保存当前节点的左右孩子的队列

     int cout, num = 1;

     InitQueue(Q1);                               // 初始化队列

     InitQueue(Q2);

     cout = Depth(Root);

     cout = (int)pow(2.0, cout*1.0)-1;          //深度为K的二叉树的结点总数

     if (Root == NULL)                                //树为空则返回空的Q2

            return Q2;

     BiTree p = Root;                             // 临时保存树根Root到指针p中

            EnQueue(Q2, p);                             // 访问根节点,存到第二个队列中,把Visite()函数改为入队列2

     if (p->lchild)      

             EnQueue(Q1, p->lchild);                // 若存在左孩子,左孩子进队列1

      if (p->rchild)        

             EnQueue(Q1, p->rchild);                // 若存在右孩子,右孩子进队列1

      while (num <= cout)   {                 //将从树根到最后一个结都放入队列2中(包括中间的空结点)便于以树形打印二叉树              

            DeQueue(Q1, p);                                                 // 出队列

             EnQueue(Q2, p);                                    // 访问根节点,存到第二个队列中

             if (p->lchild)               

                    EnQueue(Q1, p->lchild);                       // 若存在左孩子,左孩子进队列1

             else

                    EnQueue(Q1, NullBiTree());                  //否则以空树入队列1

             if (p->rchild)              

                    EnQueue(Q1, p->rchild);                // 若存在右孩子,右孩子进队列1

             else

                    EnQueue(Q1, NullBiTree());

             num++;

      }

      return Q2;

}

//层次遍历打印

void Print(LinkQueue Q, BiTree T){                  //Q为进行层次遍历得到的队列

      int i, j;

      int c, n;

      BiTree t;

      InitBiTree(t);

      c = Depth(T);                                         //深度

      printf("\n\n");

      for(i=0; i

             n = (int)pow(2.0, i*1.0);           //每一层的结点个数

             for(j=1; j<=n; j++){

                    DeQueue(Q, t);

                    if(i == 0){                                 //第一层

                           if(t->data.tag == INT)

                                  printf("\t\t\t\t %d", t->data.n);

                           else if(t->data.tag==CHAR || t->data.tag==OPER)

                                  printf("\t\t\t\t %c", t->data.c);

                           else if(t->data.tag == DOU)

                                  printf("\t\t\t\t %lf", t->data.num);

                    }

                    if(i == 1){                                        //第二层

                           if(t->data.tag == INT)

                                  printf("\t\t%d\t\t", t->data.n);

                           else if(t->data.tag==CHAR || t->data.tag==OPER)

                                  printf("\t\t%c\t\t", t->data.c);

                           else if(t->data.tag == DOU)

                                  printf("\t\t%lf\t\t", t->data.num);

                    }

                    if(i == 2){                                               //第三层

                           if(t->data.c == '#')                    //空结点

                                  printf("  \t \t");

                           if(t->data.tag == INT)

                                  printf("  \t%d\t ", t->data.n);

                           else if((t->data.tag==CHAR || t->data.tag==OPER) && t->data.c != '#')

                                  printf("  \t%c\t ", t->data.c);

                           else if(t->data.tag == DOU)

                                  printf("  \t%lf\t ", t->data.num);

                    }

                    if(i == 3){                                               //第四层

                           if(t->data.c == '#')                    //空结点

                                  printf("   \t");

                           if(t->data.tag == INT)

                                  printf("   %d\t", t->data.n);

                           else if((t->data.tag==CHAR || t->data.tag==OPER) && t->data.c != '#')

                                  printf("   %c\t", t->data.c);

                           else if(t->data.tag == DOU)

                                  printf("   %lf\t", t->data.num);

                    }

                    if(i == 4){                                               //第五层

                           if(t->data.c == '#')                    //空结点

                                  printf("    ");

                           if(t->data.tag == INT)

                                  printf("    %d", t->data.n);

                           else if((t->data.tag==CHAR || t->data.tag==OPER) && t->data.c != '#')

                                  printf("    %c", t->data.c);

                           else if(t->data.tag == DOU)

                                  printf("    %lf", t->data.num);

                    }

             }

             printf("\n\n\n");

      }

}

//检查表达式中是否含有变量,若有返回TRUE

Status Check(BiTree T)  { 

    BiTree t;

      InitBiTree(t);

      LinkQueue Q;

      InitQueue(Q);

      Q = HierarchyBiTree(T);

      while(!(Q.front == Q.rear)){

             DeQueue(Q, t);

             if(t->data.tag == CHAR){

                    if(isalpha(t->data.c))

                           return TRUE;            

             }

      }

      return FALSE;

//后序遍历,利用栈对表达式进行运算,最后结果以结点的形式存放在栈中

Status Caculate(BiTree T, SqStack &S){

      if(Check(T)){

             printf("对不起,此表达式中含有变量,请全部赋值后再计算!\n");

             return ERROR;

      }

      TElemTag te;

      BiTree T1, T2, T3;

      InitBiTree(T1);

      InitBiTree(T2);

      InitBiTree(T3);

      te.tag = DOU;

      te.num = 0.0;

      CreateBiTree(T3, te);               //T3是用来保存浮点型的运算结果的

      double d1, d2;

      if(T){

        Caculate(T->lchild, S);                 //后序遍历

             Caculate(T->rchild, S);

             if(T->data.tag==DOU)

                    Push(S, T);

             else if(T->data.tag == INT){

                    T3->data.num = (double)T->data.n;

                    Push(S, T3);

             }

             else if(T->data.tag==OPER){         //遇操作符,则进行运算

                    Pop(S, T2);

                    Pop(S, T1);

                    switch(T->data.c){

                           case '+' : if(T1->data.tag == INT)                 //先把int转为double

                                                   d1 = (double)T1->data.n;

                                            else

                                                   d1 = T1->data.num;

                                            if(T2->data.tag == INT)

                                                   d2 = (double)T2->data.n;

                                            else

                                                   d2 = T2->data.num;

                                            T3->data.num = d1 + d2;

                                            Push(S, T3); 

                                            break;

                           case '-' : if(T1->data.tag == INT)

                                                   d1 = (double)T1->data.n;

                                            else

                                                   d1 = T1->data.num;

                                            if(T2->data.tag == INT)

                                                   d2 = (double)T2->data.n;

                                            else

                                                   d2 = T2->data.num;

                                            T3->data.num = d1 - d2;

                                            Push(S, T3);

                                            break;

                           case '*' : if(T1->data.tag == INT)

                                                   d1 = (double)T1->data.n;

                                            else

                                                   d1 = T1->data.num;

                                            if(T2->data.tag == INT)

                                                   d2 = (double)T2->data.n;

                                            else

                                                   d2 = T2->data.num;

                                            T3->data.num = d1 * d2;

                                            Push(S, T3); 

                                            break;

                           case '/' : if(T1->data.tag == INT)

                                                   d1 = (double)T1->data.n;

                                            else

                                                   d1 = T1->data.num;

                                            if(T2->data.tag == INT)

                                                   d2 = (double)T2->data.n;

                                            else

                                                   d2 = T2->data.num;

 

                                            if(d2 == 0.0){ 

                                                      

                                                   printf("对不起,除数不能为0,计算失败\n"); 

                                                   return ERROR; 

                                            }else{

                                                   T3->data.num = d1 / d2;

                                                   Push(S, T3); 

                                                   break;

                                            }             

                           case '^' : if(T1->data.tag == INT)

                                                   d1 = (double)T1->data.n;

                                            else

                                                   d1 = T1->data.num;

                                            if(T2->data.tag == INT)

                                                   d2 = (double)T2->data.n;

                                            else

                                                   d2 = T2->data.num;

                                            T3->data.num = pow(d1, d2);

                                            Push(S, T3); 

                                            break;

                           default : break;

                    }

             }  

    }

      return OK;

}

//对表达式中的所有变量V的赋值c,参数flag为表示是否赋值过的标志  

void Assign(BiTree T, char V, int c, int *flag)  { 

    if(T)   { 

        if(T->data.tag==CHAR && T->data.c==V){                //如果找到要赋值的变量,赋值  

         

            T->data.tag = INT; 

            T->data.n = c; 

            *flag = 1; 

        } 

        Assign(T->lchild, V, c, flag);              //递归左子树  

        Assign(T->rchild, V, c, flag);              //递归左子树  

    } 

//设计者信息

void Designer(){

    printf("\t\t    Design By XXX\n");

    printf("\t\t _______________________\n");

    printf("\t\t|   姓名 : |  XXX   |\n");

    printf("\t\t|-----------------------\n");

    printf("\t\t|   班级:  |  计科1    |\n");

    printf("\t\t|-----------------------\n");

    printf("\t\t|   学号:  | 3112005763|\n");

    printf("\t\t ~~~~~~~~~~~~~~~~~~~~~~~\n");

    printf("\tCopyright @CKW, All Rights Reserved\n\n");

}

//取得当地时间

void GetTime(){

      char *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

      time_t timep; struct tm *p; time(&timep);

      p = localtime(&timep);                                                                                   //取得当地时间

      printf ("%d/%d/%d ", (1900+p->tm_year), (1+p->tm_mon), p->tm_mday);

      printf("%s\t%d:%d:%d\n", wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);

}

//主菜单

void Menu(){

      printf("\n\t现在的时间是:");

      GetTime();

      printf("\n\t\t欢迎使用《表达式类型的表示》系统\n");

    printf("\n\t\t请输入你想要进行的操作:\n");

    printf("\t1.【输入后缀表达式创建二叉树】2.【输出二叉树的形状】\n");

    printf("\t3.【输出二叉树的前缀和中缀】  4.【对表达式中的变量赋值】\n");

    printf("\t5.【计算表达式的值】\t      6.【求二叉树的深度】\n");

      printf("\t\t\t0.【退出系统!】\n");

}

主函数

void main(){

      system("color a");                                   //设置字体颜色为绿色,其实颜色不重要。。。

      char n;

      Status flag = ERROR;

      BiTree T, T1;

      SqStack S, S1;

      LinkQueue Q;

      InitQueue(Q);

      InitStack(S1);

      InitStack(S);

      InitBiTree(T);

      InitBiTree(T1);

      Designer();

      while(1){     

        Menu();

        scanf(" %c", &n);                                //此处输入的是字符,因为字符比数字容易处理

                                                          // %c前面有个空格是因为scanf()的缓冲区处理

        if(n == '0')                                     //如果输入0字符即退出系统

            break;                                      

        else if('1'<=n && n<='6'){                        //1 ~ 6之间

            switch(n){            

                case '1': {

                        printf("\n请输入正确的后缀表达式(为了便于以树的形状输出二叉树,请保证构造的二叉树深度不超过4):\n");

                                         printf("如果输入多字母的变量,即系统只取最后一个字符作为变量,如果最后一个字符为数字,即当做数字处理。\n");

                                         printf("格式为(X X X):\n");

                                         if(!T){

                                                Destory(T);

                                         }

                                         if(!StackEmpty(S))

                                                ClearStack(S);

                        Input(S, T);

                                         if(!Judge(S)){                    //输入的是不正确的后缀表达式

                                                flag = ERROR;

                                                printf("对不起,你输入的不是正确的后缀表达式,请重新输入!\n");

                                         }else{

                                                flag = OK;

                                                printf("二叉树已构建成功!\n\n\n");

                                         }

                        break;

                }

                case '2': {

                                         if(flag != OK){

                                                printf("表达式还没有构造, 请先构造表达式!\n");

                                                break;

                                         }

                        printf("此二叉树的形状为:\n");

                        GetTop(S, T);                                                //此二叉树放在一个栈当中,现在取出来

                                         Q = HierarchyBiTree(T);                               //利用队列对此二叉树进行层次遍历,并把结果放在队列中

                                         Print(Q, T);                                             //按形状打印出来

                        break;

                }

                case '3': {

                                         if(flag != OK){

                                                printf("表达式还没有构造, 请先构造表达式!\n");

                                                break;

                                         }

                        printf("二叉树的前缀序列为:\n");

                                         Perorder(T);

                                         printf("\n\n");

                        printf("二叉树的中缀序列为:\n");

                        Inorder(T);

                                         printf("\n\n");

                        break;

                }

                case '4': {

                                         if(flag != OK){

                                                printf("表达式还没有构造, 请先构造表达式!\n");

                                                break;

                                         }

                        int Assign_tag = ERROR;                            //是否赋值成功的标记   

                                         char ch;                                            //保存要赋值的变量的名   

                                         int n;                                                       //保存要赋的值(为了方便,统一赋值为整型)  

                                         printf("请输入要赋值的变量名: ");  

                                         ch = getchar(); 

                                         ch = getchar();

                                         printf("\n要赋值为(为了方便,统一赋值为整型): ");  

                                         scanf("%d", &n); 

                                         Assign(T, ch, n, &Assign_tag); 

                                         if(Assign_tag == OK){ 

                                                printf("赋值成功!\n"); 

                                                printf("赋值后表达式为:\n"); 

                                                GetTop(S, T);                                                //此二叉树放在一个栈当中,现在取出来

                                                Q = HierarchyBiTree(T);                               //利用队列对此二叉树进行层次遍历,并把结果放在队列中

                                                Print(Q, T);                                             //按树形状打印出来

                                         }else 

                                                printf("表达式里没有 %c 这个变量!\n", ch); 

                      

                        break;

                }

                case '5': {

                                         if(flag != OK){

                                                printf("表达式还没有构造, 请先构造表达式!\n");

                                                break;

                                         }

                                         if(Caculate(T, S1) == OK){                   //最终结果作为一个结点放在栈S1中

                                                GetTop(S1, T1);                              //把结果取出放在树根T1中

                                                printf("表达式的结果是:");

                                                printf("%lf\n", T1->data.num);

                                         }

                        break;

                }           

                case '6': {

                                         if(flag != OK){

                                                printf("表达式还没有构造, 请先构造表达式!\n");

                                                break;

                                         }

                        int d = Depth(T);

                                         printf("二叉树的深度为: %d\n", d);

                        break;

                }                      

             

              default: break;

            }                

        }else{

            printf("对不起,您输入的操作有误,请重新输入!\n");

        }   

    }

    printf("\t\t\t已安全退出,感谢使用!\n");      

}

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