数据结构课程设计 表达式类型的实现
来源:互联网 发布: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; } }}
- 数据结构课程设计 表达式类型的实现
- 数据结构课程设计---------用栈来实现表达式求值
- 数据结构课程设计---------用栈来实现表达式求值
- 数据结构课程设计-表达式求值
- {数据结构课程设计}校园导游的多功能实现
- 数据结构课程设计 算术表达式求值
- 利用栈求表达式的值(数据结构课程设计)
- 数据结构的课程设计
- 数据结构-图的课程设计
- 数据结构课程设计-通讯录管理系统的设计与实现
- 内部排序算法的实现与比较-数据结构课程设计
- 数据结构课程设计··表达式翻译
- 我的数据结构的课程设计
- 表达式--栈的实现(数据结构)
- 【数据结构】中缀表达式的实现
- 数据结构课程设计:哈希表的设计
- 数据结构课程设计--数组(顺序实现)
- 数据结构课程设计--广义表(链式实现)
- Java设计模式-----Abstract Factory抽象工厂模式
- [ARM Linux] Qt: Qtopia 2.2 桌面和程序 在ARM-LINUX上发布
- 数据结构课程设计 算术表达式求值
- JQuery页面随滚动条动态加载效果实现
- POJ1275 Cashier Employment
- 数据结构课程设计 表达式类型的实现
- 查看数据库死锁的进程及清除sleeping进程(Kill__Sleeping_Processes)
- php中array_multisort()对多维数组进行排序,相当于数据库查询是order by多字段排序。。超好用
- QWidget,QMainWindow和QDialog的区别
- gdb里面的堆栈调试命令
- 获取RichEditCtrl图片及如何使用在你的程序中~
- 自定义JavaScript类
- Sql Server内存瓶颈(读书笔记)
- js处理年月日下拉菜单变化