数据结构课程设计 表达式类型的实现

来源:互联网 发布:php pdo sqlserver 编辑:程序博客网 时间:2024/05/22 17:24

题目:写一个程序,实现基于二叉树表示的算术表达式Expression的操作。

头文件:应保存为“Expression.h”

#include<stdio.h>#include<string.h>#include<math.h>#include<ctype.h>#include<stdlib.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0//#define OVERFLOW 0//二叉树节点类型typedef enum { INT, CHAR } ElemTag; //INT为实型,CHAR为字符型 //二叉树数据域 typedef struct TElemTag{    ElemTag tag;      union    {        int num;        char c;    };} TElemTag;//二叉树链式存储结构 typedef struct BiTNode{    TElemTag data; //数据域     struct BiTNode *lchild, *rchild;    //左右孩子指针 } BiTNode, *BiTree;typedef BiTree SElemType;   //栈SqStack的元素//栈的顺序存储结构 #define STACK_INIT_SIZE 30  //初始存储空间 #define STACKINCREMENT 5    //存储空间增量 typedef struct SqStack{    SElemType *base;    SElemType *top;    int stacksize;} SqStack;int 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;}int StackEmpty(SqStack S){    if(S.top == S.base)        return TRUE;    else        return FALSE;}int 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;}int Pop(SqStack *S, SElemType *e){    if((*S).base == (*S).top)       return ERROR;    *e = *--(*S).top;    return OK;}int GetTop(SqStack S, SElemType *e){    if(S.top > S. base)    {        *e = *(S.top - 1);        return OK;    }    return ERROR;}

主程序:

#include"Expression.h"//判断是否操作符int isoperator(char optr){    switch(optr)    {        case '+':        case '-':        case '*':        case '/':        case '^': return TRUE;        default: return FALSE;    }}//判断字符a的类型void Judge(BiTree *E, char a){    if(isdigit(a))//a是常量    {        (*E) -> data.tag = INT;        (*E) -> data.num = a - '0';    }    else//a为字符    {        (*E) -> data.tag = CHAR;        (*E) -> data.c = a;    }}int ReadExpr(BiTree *E, char *expr){    int i, len;//len为expr的长度    SqStack S;//操作符栈    BiTree p, q;//辅助变量         gets(expr);    len = strlen(expr);    //printf("len = %d\n", len);        (*E) = (BiTree)malloc(sizeof(BiTNode));//申请根节点    (*E) -> lchild = NULL;    (*E) -> rchild = NULL;        if(len == 1)//表达式长度为1时    {        if(isdigit(expr[0]))        {            (*E) -> data.tag = INT;            (*E) -> data.num = expr[0] - '0';            return OK;        }        else if(isalpha(expr[0]))        {            (*E) -> data.tag = CHAR;            (*E) -> data.c = expr[0];            return OK;        }        else        {            printf("输入的字符不是运算符也不是变量常量,错误!\n");            return ERROR;        }    }    else    {        Judge(E, expr[0]);        InitStack(&S);//初始化栈        q = (*E);                Push(&S, q);//        Push(&S, q);//根结点入栈两次是为判断先序输入的表达式是不是正确的表达式                for(i = 1; i < len && !StackEmpty(S); i++)        {            p = (BiTree)malloc(sizeof(BiTNode));            Judge(&p, expr[i]);            p -> lchild = NULL;            p -> rchild = NULL;                        if(isoperator(expr[i])) //是运算符,运算符入栈            {                if( !q -> lchild )//左孩子不空,往左走                {                    q -> lchild = p;                    Push(&S, p);                    q = p;                }                else//否则右孩子不空,往右走                {                    q -> rchild = p;                    Push(&S, p);                    q = p;                }            }            else//不是运算符,出栈            {                if( !q -> lchild )                {                    q -> lchild = p;                    Pop(&S, &q);                }                else                {                    q -> rchild = p;                    Pop(&S, &q);                }             }        }//end for                if(StackEmpty(S) && i >= len)        {            //printf("SM:%d  i:%d", StackEmpty(S), i);            return OK;//表达式为前缀表达式        }        else        {            //printf("SM:%d  i:%d", StackEmpty(S), i);            return ERROR; //不是前缀表达式        }    }}//如果两个字符是运算符,比较两个运算符的优先级,a比b优先,返回OK,否则返回ERRORint PriCompare(char a, char b){    if(isoperator(a) && isoperator(b))    {        if(a == '^')        {            if(b != '^')                return OK;//a的优先级比b高            else                return ERROR;        }        else if( a == '*' || a == '/')        {            if(b == '*' || b == '/' || b == '^')                return ERROR;            else                return OK;        }        else//其余a的优先级不比b高            return ERROR;    }    else//不是运算符        return ERROR;}//中序遍历输出中序缀表达式void WriteExpr(BiTree E){    if(E)//树不为空    {//先递归左子树        if(E -> lchild && E -> lchild -> data.tag == CHAR)//左孩子不空且为字符{if(PriCompare(E -> data.c, E -> lchild -> data.c))//E的优先级比其左孩子的高{  //带括号输出表达式printf("(");WriteExpr(E -> lchild);printf(")");}else//不带括号输出左子树WriteExpr(E -> lchild);}else//左子树WriteExpr(E -> lchild);//访问并输出根节点if(E -> data.tag == INT){printf("%d", E -> data.num);}else{printf("%c", E -> data.c);}//后递归右子树if(E -> rchild && E -> rchild -> data.tag == CHAR)//右孩子不空且为字符{if(PriCompare(E -> data.c, E -> rchild -> data.c))//E的优先级比其右孩子的高{ //带括号输出表达式printf("(");WriteExpr(E -> rchild);printf(")");            }else//不带括号输出右子树WriteExpr(E -> rchild);}else//输出右子树WriteExpr(E -> rchild);    }}//对表达式中的所有变量V的赋值,参数flag为表示是否赋值过的标志void Assign(BiTree *E,char V,int c,int *flag){if(*E){if((*E)->data.tag==CHAR&&(*E)->data.c==V)//如果找到要赋值的变量,赋值{            (*E)->data.tag=INT;            (*E)->data.num=c;            *flag=1;        }Assign(&((*E)->lchild),V,c,flag);//递归左子树Assign(&((*E)->rchild),V,c,flag);//递归左子树}}int powINT(int x, int exp){    int i, result = 1;    for(i = 1; i <= exp; i++)        result *= i;    return result;}int Operate(int a, char oprt, int b){    switch(oprt)    {        case '+':return a + b;        case '-':return a - b;        case '*':return a * b;        case '/':            if(b != 0)                return a / b;            else            {                printf("除数不能为0\n");                break;            }        case '^':return powINT(a, b);        default:break;    }}//检查是否还有没赋值的变量 int Check(BiTree E){    if(E && E -> data.tag == CHAR)//树不空且为结点为字符     {        if(isalpha(E -> data.c))             return ERROR;                     Check(E -> lchild);        Check(E -> rchild);        return OK;    }}int Value(BiTree E){    if(E)    {        //结点的左右孩子空, 是叶子结点, 返回其值         if(!E -> lchild && !E -> rchild && E -> data.tag == INT)            return E -> data.num;                //以后根遍历次序求解表达式的值        return Operate(Value(E -> lchild), E -> data.c, Value(E -> rchild));    }}void CompoundExpr(char P, BiTree *E1, BiTree E2){    BiTree E;    E = (BiTree)malloc(sizeof(BiTNode));    E -> data.tag = CHAR;    E -> data.c = P;    E -> lchild = *E1;    E -> rchild = E2;    (*E1) = E;    printf("\n表达式E复合成功!其表达式变为:\n");    WriteExpr(E);}//输出选择菜单int menu(){    printf("1.输入前缀表达式\n");    printf("2.输出表达式的中缀表示式\n");     printf("3.对变量赋值\n");    printf("4.计算表达式的值\n");    printf("5.构造一个新的复合表达式\n");    printf("0.退出\n\n");    printf("请输入你的选择: ");     int choice = -1;    scanf("%d%*c", &choice);    return choice;}int main(){    BiTree E,newE;  //二叉树     char EXPR[81];  //前缀表达式     int flag = ERROR, flag2 = ERROR;   //标记表达式是否赋值成功, OK为成功, ERROR为失败    char V; //要赋值的变量     char P; //合并的操作符     while(1)    {        switch(menu())        {            case 1:           do{                    printf("请输入正确的前缀表达式: ");                    flag = ReadExpr(&E, EXPR);                    if(flag == OK)                        printf("表达式构造成功.\n\n");                    else                    {                        printf("表达式构造失败.\n");                        printf("请输入正确的前缀表达式: ");                    }                }while(flag == ERROR);                if(flag == OK)                {                    printf("前缀表达式的中缀表示式为: ");                    WriteExpr(E);                    printf("\n\n");                }                break;            case 2:                if(flag == OK)                 {                    printf("前缀表达式的中缀表示式为: ");                    WriteExpr(E);                    printf("\n");                }                else                    printf("表达式还没有构造, 请先构造表达式.\n");                break;            case 3:                if(flag == OK)                {                    int Assign_tag = ERROR;//是否赋值成功的标记                     char ch;//保存要赋值的变量                     int n;//保存要赋的值                     printf("请输入要赋值的变量名: ");                     ch = getchar();                    printf("\n要赋值为: ");                     scanf("%d", &n);                    Assign(&E, ch, n, &Assign_tag);                    if(Assign_tag == OK)                    {                        printf("赋值成功!\n");                        printf("赋值后表达式为:");                        WriteExpr(E);                        printf("\n");                    }                    else                        printf("表达式里没有 %c 这个变量!\n", ch);                }                else                    printf("表达式还没有构造, 请先构造表达式.\n");                break;            case 4:                if(flag == OK)                {                    int chk = ERROR;                    chk = Check(E);                    if(chk == OK)//检查表达式里是否还有未赋值的变量                     {                        WriteExpr(E);                        printf("=%d\n", Value(E));                    }                    else                    {                        printf("表达式里还有未赋值变量!\n\n");                    }                 }                break;            case 5:                if(flag == OK)                {                    do{                        printf("请输入新的表达式: ");                                                flag2 = ReadExpr(&newE, EXPR);                                                if(flag2)                            printf("表达式2构造成功.\n");                        else                        {                            printf("表达式2构造失败.\n");                            printf("请输入正确的前缀表达式.\n");                        }                    }while(flag2 == ERROR);                                        printf("前缀表达式2的中缀表示式为: ");                    WriteExpr(newE);                    printf("\n\n");                                        do{                        printf("请输入运算符: ");                        P = getchar();                    }while(!isoperator(P));                                         CompoundExpr(P, &E, newE);                                        printf("复合的前缀表达式的中缀表示式为: ");                    WriteExpr(E);                    printf("\n\n");                }                break;            case 0:                printf("\n请按任意键退出!\n");                getch();                exit(0);            default:                printf("\n输入有误!请按任意键回到主菜单重新选择!\n");getch();                break;        }    }}