1、数据结构实验报告课程设计实验报告实验名称: 表达式类型的实现编译环境:硬件:PC软件:VS2010问题描述一个表达式和一棵二叉树之间, 存在着自然的对应关系。 写一个程序, 实现基于二叉树 表示的算术表达式 Expression 的操作。基本要求假设算术表达式 Expression可以含有变量(az)、常量(09)和二元运算符(+,-,*, / , A (乘幕)。实现以下操作。( 1) ReadExpr(E) 以字符序列的形式输入语法正确的前缀表示式并构造表达式 E。( 2) WriteExpr(E) 用带括弧的前缀表示式输出表达式 E。(3) Assign(V , c)实现对变量 V的赋值(
2、V=c),变量的初值为 0。( 4) Value(E) 对算术表达式 E 求值。(5) CompoundExpr(P, E1, E2)构造一个新的复合表达式 (E1)P(E2)。选作内容:(1)增加常数合并操作 MergeConst(E) 合并表达式中E的所有常数运算。 例如:表达式 E=2+2*1-A 进行合并常数的操作后,求得 E=4-A( 2)以表达式的原书写形式输入需求分析1.以字符序列的形式输入语法正确的中缀表示式并构造表达式 E。即要根据正确的前缀式建立一棵二叉树 T。2 用带括弧的前缀表达式输出表达式 E。即要求在前缀遍历二叉树的时候考虑运算符的优先级,在适当的位置输出括弧。3.
3、 实现对变量 V的赋值(V= c),变量的初值为0。那就在中缀遍历二叉树的过程中比较结点的 值是否为V,找到V以后将c赋给V。4. 对算术表达式 E 求值。如果表达式中有变量的话,首先提示用户表达式中变量,建议先执行 操作3 (实现对变量 V赋值),执行完后再回来执行表达式求值这一步骤。表达式求值利用递归, 如果某个结点的值为运算符并且它的左右孩子结点的值为数据, 那么就把(左孩子)(运算符)(右 孩子)的结果赋给该结点。一层一层往上,最后只剩下一个根结点。此时根结点的值就是表达式 E的值。5. 构造一个新的复合表达式( E1) P (E2)。只要先构造表达式 E1的二叉树和 E2的二叉树,然
4、 后利用 P 把这两棵二叉树连接起来构成一棵新的二叉树。6.合并表达式 E 中所有常数运算。此原理类似于对表达式 E 求值,不同之处只在于该功能只对 常数合并。概要设计1. 树的抽象数据类型定义 :ADT Tree数据对象 D: D 是具有相同特性的数据元素的集合。数据关系R:若D为空集,则称为空树;若D仅含一个数据元素,则R为空集,否则R=H,H 是如下二元关系:(1)在D中存在唯一的称为根的数据元素 root,它在关系H下无前驱;(2)若 D-root工 ,则存在 D-root 的一个划分 D1,D2,Dm(m0),对任意 j丰k(1=j,k=m)有Dj A Dk = ,且对任意的i(1
5、i m),唯一存在数据 元素 Xi Di,有 H;(3)对应于 D-root 的划分,H - 有唯一的一个划分 H1,H2Hm(m0,对任意j丰k(1=j,k=m)有Dj A Dk = ,且对 任意的i(1 data=si;p-lchild=NULL; p-rchild=NULL; return p;/ 以下是 i!=j 的情况if(i!=j)for(k=i;k=j;k+) if(sk=+|sk=-)plus+; posi=k; if(plus=0) for(k=i;kdata=sposi; p-lchild=ReadExpr(s,i,posi-1); p-rchild=ReadExpr(s,
6、posi+1,j); return p;/ void WriteExpr(BTNode *b) / 把输入的表达式转换为相应的二叉树,并以前缀表达式的 形式输出if(b!=NULL)printf(%c,b-data);if(b-lchild!=NULL|b-rchild!=NULL)printf();WriteExpr(b-lchild );if(b-rchild!=NULL) printf(,);WriteExpr(b-rchild); printf();char Seek(char s,int k)/ 判断是否有字母输入char a1=0;int i;for(i=0;i=A&si=a&si
7、=z) return a0=1;void Assign(char s,char i,char j)for(int p=0;p=strlen(s)-1;p+) if(sp=i)sp=j;void CompoundExpr(char E1,char E2,char p)/ 复合表达式char NewEMaxSize,q1;int k=0,i;BTNode *bt1,*bt2,*T;if(p=+|p=-)/ 复合函数为 +或- 是应怎样复合for( i=0;istrlen(E1);i+)NewEi=E1i;NewEstrlen(E1)=p;for( k=0;k=0&sk-1=0&sk+1=9) /
8、判断是否为数字 /*FX=sk-1*sk+1;sk-1=FX;*/sk-1=(sk-1-48)*(sk+1-48)+48;for(int i=k;i=0&sk-1=0&sk+1=9) sk-1=(sk-1-48)/(sk+1-48)+48;for(int i=k;i=0&sk-1=0&sk+1=9) sk-1=(sk-1-48)+(sk+1-48)+48;for(int i=k;i=0&sk-1=0&sk+1=9) sk-1=(sk-1-48)-(sk+1-48)+48;for(int i=k;istrlen(s);i+) si=si+2;printf( 常数合并后为: %s,s);void
9、MergeConst(char s)/ 常数合并int i,j,n;for(i=0;istrlen(s);i+)if(si=*|si=/)Conbination(s,i);for(j=0;jstrlen(s);j+)if(sj=+|sj=-) Conbination(s,j); void main() double fx=0;BTNode *b;int i=0,j=0;char sMaxSize, yesORno,value,getvalue,GetDigitl=NULL,p,E17,E23,e1,e2; printf( nn 表达式类型实现的使用说明: nn);printf( 表达式暂时还不
10、能进行括号操作,请不要输入括号, nn); printf(” 数字的输入只能是一位数(0-9),字母的输入a-z或A-Znn);printf( 表达式输入时请按以下形式输入: A-S+Dnn);printf(*nn);printf( 1. 输入表达式 2. 输出表达式 nn);printf( 3. 对变量赋值 4. 对表达式求值 nn); printf( 5. 复合表达式 6. 常数合并 nn);printf( 7. 返回 nn);printf(*nn);printf( 请输入选择( 1-7 );while(GetDigitl=getchar()!=7) switch(GetDigitl) c
11、ase 1:a+b*c/dnn);printf(nn 请以中缀表达式形式输入表达式,例如 printf( 你的输入 );getchar();gets(s); / 以中缀表达式形式输入表达式printf(n);printf( 你输入的表达式为 :%sn,s); b=ReadExpr(s,0,strlen(s)-1);printf(n 请输入选择( 1-7 ) n);break;case 2:printf(n 对应的二叉树: );WriteExpr(b);printf(nn);printf(n 请输入选择( 1-7 ) n); break;case 3: while(yesORno=Seek(s,
12、strlen(s)-1)=1)printf( 表示式中有变量! n); getchar();printf( 需要赋值的变量: ); value=getchar();getchar();printf( 变量值: ); getvalue=getchar();Assign(s,value,getvalue); b=ReadExpr(s,0,strlen(s)-1); printf(n 对应的二叉树: );WriteExpr(b);printf(n 请输入选择( 1-7 ) n); break;case 4:yesORno=Seek(s,strlen(s)-1);if(yesORno=1)printf
13、( 表达式中有未知变量,请选择 3进行变量赋值 n); else fx=Expression(s); /* 表达式求值 */printf(n 表达式的运算结果为 : %f n,fx);printf(n 请输入选择( 1-7 ) n);break;case 5:printf( 请从( +、- 、*、/ )中选择一个作为复合符号 n);printf( 你的选择是: );getchar();p=getchar();printf(n);printf( 请输入要复合的第一个表达式: );getchar();gets(E1);printf(n);printf( 请输入要复合的第二个表达式 :);gets(
14、E2);printf(n);CompoundExpr(E1,E2,p);printf(n 请输入选择( 1-7 ) n);break;case 6: MergeConst(s);printf(n 请输入选择( 1-7 ) n);break;/ 一下是表达式求值函数#includeMyExpression.hdouble Expression(char *oldexp) / 表达式计算函数,输入的是表达式字符串 char notationMAX_NOTATION_LEN, / 存放当前符号扫描读入的符号 op1,op2,expMAX_EXP_LEN; / 存放当前操作表达式 char flag=
15、CONTINUE_READ_NEXT_NOTATION; / 判别是否继续扫描下去 int prior; / 存放算符优先级别比较结果 : op2op1 : 1strcat(exp,#); /push(OPTR,#,0.0,&s);操作数处理运算符处理运算符出栈刚出栈的运算符再次进栈 当前运算符优先级别高,进栈/ 暂停读入下一个表达式符号使当前运算符与栈顶运算符再作一次比较s.OpdStackTop=s.OpStackTop=0;把原表达式复制给当前操作表达式strcpy(exp,oldexp); /把#接到exp后面,原exp最后面的 0 被取消/ 初始化表达式计算堆栈while(1)if(
16、 flag=CONTINUE_READ_NEXT_NOTATION ) GetNextNotation (notation,exp);else /* 有运算结果进操作数栈后 */flag=CONTINUE_READ_NEXT_NOTATION;if ( GetTypeOfNotation( notation )=OPND ) opnd2 = atof(notation);push(OPND,NULL,opnd2,&s); /else / op2 = notation 0;op1 = (char) pop(OPTR,&s); /prior = CompareOpPrior(op2,op1);if
17、 ( prior 0 ) /op2 0 ) /op2 op2 opnd2 = pop(OPND,&s) ;opnd1 = pop(OPND,&s);opnd2 = calculate(opnd1,op1,opnd2 ); push( OPND, NULL,opnd2,&s); flag=STOP_READ_NEXT_NOTATION;/if(prior=0) /op2 = op1 的情况处理 if( op2=#)return pop(OPND,&s) ;/ 结束运算,将运算结果从堆栈中弹出void push(char type, char op,double opnd,ExpressionCa
18、lculateStack *s) if(type=OPND) s-OpdStacks-OpdStackTop+= opnd;else s-OpStacks-OpStackTop+ = op;double pop(char type,ExpressionCalculateStack *s) if(type=OPND) / 是操作数栈 return s-OpdStack-s-OpdStackTop;else / 是运算符栈 return (double) (s-OpStack-s-OpStackTop);double calculate(double opnd1,char op,double opnd2 ) switch(op) case +: return opnd1+opnd2; case -: return opnd1-opnd2;case *: return opnd1*opnd2;case /: if( opnd2!=0.0) return opnd1/opnd2; else return 0.0;return 0.0;: 操作数no
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1