数据结构实验报告.docx
- 文档编号:4535728
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:21
- 大小:161.81KB
数据结构实验报告.docx
《数据结构实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告.docx(21页珍藏版)》请在冰豆网上搜索。
数据结构实验报告
课程设计实验报告
实验名称:
表达式类型的实现
编译环境:
硬件:
PC软件:
VS2010
问题描述
一个表达式和一棵二叉树之间,存在着自然的对应关系。
写一个程序,实现基于二叉树表示的算术表达式Expression的操作。
基本要求
假设算术表达式Expression可以含有变量(a〜z)、常量(0~9)和二元运算符(+,-,
*,/,A(乘幕))。
实现以下操作。
(1)ReadExpr(E)——以字符序列的形式输入语法正确的前缀表示式并构造表达式E。
(2)WriteExpr(E)——用带括弧的前缀表示式输出表达式E。
(3)Assign(V,c)――实现对变量V的赋值(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.实现对变量V的赋值(V=c),变量的初值为0。
那就在中缀遍历二叉树的过程中比较结点的值是否为V,找到V以后将c赋给V。
4.对算术表达式E求值。
如果表达式中有变量的话,首先提示用户表达式中变量,建议先执行操作3(实现对变量V赋值),执行完后再回来执行表达式求值这一步骤。
表达式求值利用递归,如果某个结点的值为运算符并且它的左右孩子结点的值为数据,那么就把(左孩子)(运算符)(右孩子)的结果赋给该结点。
一层一层往上,最后只剩下一个根结点。
此时根结点的值就是表达式E的值。
5.构造一个新的复合表达式(E1)P(E2)。
只要先构造表达式E1的二叉树和E2的二叉树,然后利用P把这两棵二叉树连接起来构成一棵新的二叉树。
6.合并表达式E中所有常数运算。
此原理类似于对表达式E求值,不同之处只在于该功能只对常数合并。
概要设计
1.树的抽象数据类型定义:
ADTTree{
数据对象D:
D是具有相同特性的数据元素的集合。
数据关系R:
若D为空集,则称为空树;若D仅含一个数据元素,则R为空集,否则R={H},H是如下二元关系:
(1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
(2)若D-{root}工©,则存在D-{root}的一个划分D1,D2,…Dm(m>0),对任意j丰k(1<=j,k<=m)有DjADk=©,且对任意的i(1€H;
(3)对应于D-{root}的划分,H-{
个划分H1,H2…Hm(m>0,对任意j丰k(1<=j,k<=m)有DjADk=©,且对任意的i(1 义的树,称为根的root的子树。 基本操作: DoubleExpression(char*exp); 功能: 算术表达式求值 doublecalculate(doubleopnd1,charop,doubleopnd2); 功能: 操作数四则运算 voidpush(char,char,double,ExpressionCalculateStack*); 功能: 入栈 doublepop(char,ExpressionCalculateStack*); 功能: 出栈 voidGetNextNotation(char*notation,char*exp); 功能: 读下一个运算符或操作数 charGetTypeOfNotation(char*notation); 功能: 判定是运算符或是操作数 intCompareOpPrior(charop2,charop1); 功能: 运算符优先级别比较 BTNode*ReadExpr(chars[],inti,intj) 功能: 读入表达式 voidWriteExpr(BTNode*b) 功能: /把输入的表达式转换为相应的二叉树,并以前缀表达式的形式输出 charSeek(chars[],intk)功能: 判断是否有字母输入voidCompoundExpr(charE1[],charE2[],charp)功能: 复合表达式 voidAssign(chars[],chari,charj) 功能: 对变量进行复制 } 流程图: Mian函数 typedefstructstack{ /* 表达式计算堆栈*/ doubleOpdStack[MAX_NOTATION_NUM];/* 操作数堆栈*/ charOpStack[MAX_NOTATION_NUM];/* 运算符堆栈*/ intOpdStackTop, /* 操作数堆栈顶指针*/ OpStackTop; /* 运算符堆栈顶指针 */ }ExpressionCalculateStack; #defineOPND'D'/* 操作数类型标志 */ #defineOPTR'R'/* 运算符类型标志 */ #defineCONTINUE_READ_NEXT_ NOTATION'C' /* 表达式扫描标志, 继续扫描*/ #defineSTOP_READ_NEXT_ NOTATION'S' /* 表达式扫描标志,暂停扫描*/ #defineMAX_NOTATION_LEN20 #defineNULL0 voiddoub push(char,char,double,ExpressionCalculateStack*);/*lepop(char,ExpressionCalculateStack*);/* 入栈*/出栈*/ void作数 GetNextNotation(char*notation,char*exp);/**/ 读下一个运算符或操 char数*/ GetTypeOfNotation(char*notation);/* 判定是运算符或是操作 /*部分子函数声明如下(主要是表达式求值函数)*/doubleExpression(char*exp);/* */ 算术表达式求值 doublecalculate(doubleopnd1,charop,doubleopnd2);/*运算*/ 操作数四则 源代码文件(MyExpression.c) #include"MyExpression.h" #include"stdlib.h" externdoubleExpression(char*oldexp);externintCompareOpPrior(charop2,charop1);externcharGetTypeOfNotation(char*notation);externvoidGetNextNotation(char*notation,char*exp);externdoublecalculate(doubleopnd1,charop,doubleopnd2);externdoublepop(chartype,ExpressionCalculateStack*s); externvoidpush(chartype,charop,doubleopnd,ExpressionCalculateStack*s); BTNode*ReadExpr(chars[],inti,intj) { BTNode*p; intk,plus=0,posi; if(i==j) { p=(BTNode*)malloc(sizeof(BTNode));p->data=s[i]; p->lchild=NULL;p->rchild=NULL;returnp; } //以下是i! =j的情况 if(i! =j) { for(k=i;k<=j;k++) {if(s[k]=='+'||s[k]=='-') { plus++;posi=k;} }if(plus==0) {for(k=i;k<=j;k++)if(s[k]=='*'||s[k]=='/') { plus++;posi=k;} } p=(BTNode*)malloc(sizeof(BTNode));p->data=s[posi];p->lchild=ReadExpr(s,i,posi-1);p->rchild=ReadExpr(s,posi+1,j);returnp; //} } } voidWriteExpr(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(")"); } } } charSeek(chars[],intk)//判断是否有字母输入 { chara[1]={0}; inti; for(i=0;i<=k;i++)if(s[i]>='A'&&s[i]<='Z'||s[i]>='a'&&s[i]<='z')returna[0]='1'; } voidAssign(chars[],chari,charj) { for(intp=0;p<=strlen(s)-1;p++)if(s[p]==i) s[p]=j; } voidCompoundExpr(charE1[],charE2[],charp)//复合表达式 {charNewE[MaxSize],q[1]; intk=0,i; BTNode*bt1,*bt2,*T; if(p=='+'||p=='-')//复合函数为+或-是应怎样复合 { for(i=0;i NewE[i]=E1[i]; NewE[strlen(E1)]=p; for(k=0;k NewE[i+1]=E2[k]; NewE[i+1]='\0'; printf("复合后的表达式为: %s\n\n",NewE); printf("其对应的二叉树为: "); T=ReadExpr(NewE,0,strlen(NewE)-1); WriteExpr(T); printf("\n"); } else {printf("复合的表达式为: ");//复合符号为*或/是应该怎样复合这两个表达式bt1=ReadExpr(E1,0,strlen(E1)-1); printf("("); WriteExpr(bt1); printf(")"); printf("%c",p); bt2=ReadExpr(E2,0,strlen(E2)-1); printf("("); WriteExpr(bt2); printf(")"); printf("\n"); } } voidConbination(chars[],intk)//对常数项进行合并 {//intFX=0; if(s[k]=='*') { if((s[k-1]>='0'&&s[k-1]<='9')&&(s[k+1]>='0'&&s[k+1]<='9'))//判断是否为数字 {/*FX=s[k-1]*s[k+1]; s[k-1]=FX;*/ s[k-1]=(s[k-1]-48)*(s[k+1]-48)+48; for(inti=k;i s[i]=s[i+2]; } } if(s[k]=='/') { if((s[k-1]>='0'&&s[k-1]<='9')&&(s[k+1]>='0'&&s[k+1]<='9')) {s[k-1]=(s[k-1]-48)/(s[k+1]-48)+48; for(inti=k;i s[i]=s[i+2]; } } if(s[k]=='+') { if((s[k-1]>='0'&&s[k-1]<='9')&&(s[k+1]>='0'&&s[k+1]<='9')){s[k-1]=(s[k-1]-48)+(s[k+1]-48)+48; for(inti=k;i } } if(s[k]=='-') { if((s[k-1]>='0'&&s[k-1]<='9')&&(s[k+1]>='0'&&s[k+1]<='9')){s[k-1]=(s[k-1]-48)-(s[k+1]-48)+48; for(inti=k;i } } printf("常数合并后为: %s",s); } voidMergeConst(chars[])//常数合并 { inti,j,n; for(i=0;i { if(s[i]=='*'||s[i]=='/') Conbination(s,i); } for(j=0;j { if(s[j]=='+'||s[j]=='-')Conbination(s,j); }voidmain(){doublefx=0; BTNode*b; inti=0,j=0; chars[MaxSize],yesORno,value,getvalue,GetDigitl=NULL,p,E1[7],E2[3],e1,e2;printf("\n\n表达式类型实现的使用说明: \n\n"); printf("表达式暂时还不能进行括号操作,请不要输入括号,\n\n");printf(”数字的输入只能是一位数(0-9),字母的输入a-z或A-Z\n\n"); printf("表达式输入时请按以下形式输入: A-S+D\n\n"); printf( **\n\n"); printf("1.输入表达式2.输出表达式\n\n"); printf("3.对变量赋值4.对表达式求值\n\n");printf("5.复合表达式6.常数合并\n\n"); printf("7.返回\n\n"); printf( **\n\n"); printf("请输入选择(1-7)"); while((GetDigitl=getchar())! ='7')switch(GetDigitl) {case'1': { a+b*c/d\n\n"); printf("\n\n请以中缀表达式形式输入表达式,例如printf("你的输入");getchar(); gets(s);//以中缀表达式形式输入表达式 printf("\n"); printf("你输入的表达式为: %s\n",s);b=ReadExpr(s,0,strlen(s)-1); printf("\n请输入选择(1-7)\n"); break; } case'2': { printf("\n对应的二叉树: "); WriteExpr(b); printf("\n\n"); printf("\n请输入选择(1-7)\n");break; } case'3': {while((yesORno=Seek(s,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("表达式中有未知变量,请选择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(E2); printf("\n"); CompoundExpr(E1,E2,p); printf("\n请输入选择(1-7)\n"); break; } case'6': {MergeConst(s); printf("\n请输入选择(1-7)\n"); break; } } } }//一下是表达式求值函数 #include"MyExpression.h" doubleExpression(char*oldexp)//表达式计算函数,输入的是表达式字符串{ charnotation[MAX_NOTATION_LEN],//存放当前符号扫描读入的符号op1,op2, exp[MAX_EXP_LEN];//存放当前操作表达式charflag=CONTINUE_READ_NEXT_NOTATION;//判别是否继续扫描下去intprior;//存放算符优先级别比较结果: op2 -1op2>op1: 1 strcat(exp,"#");// push(OPTR,'#',0.0,&s); 操作数处理 运算符处理 运算符出栈 刚出栈的运算符再次进栈当前运算符优先级别高,进栈 ///暂停读入下一个表达式符号 使当前运算符与栈顶运算符再作一次比较 s.OpdStackTop=s.OpStackTop=0; 把原表达式复制给当前操作表达式 strcpy(exp,oldexp);// 把’#'接到exp后面,原exp最后面的‘\0'被取消 //初始化表达式计算堆栈 while (1) { if(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(prior<0)//op2 { push(OPTR,op1,0.0,&s);// push(OPTR,op2,0.0,&s);// } if(prior>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=='#')returnpop(OPND,&s);//结束运算,将运算结果从堆栈中弹出 } } voidpush(chartype,charop,doubleopnd,ExpressionCalculateStack*s){ if(type==OPND)s->OpdStack[s->OpdStackTop++]=opnd; elses->OpStack[s->OpStackTop++]=op; } doublepop(chartype,ExpressionCalculateStack*s) {if(type==OPND)//是操作数栈returns->OpdStack[--s->OpdStackTop]; else//是运算符栈return(double)(s->OpStack[--s->OpStackTop]); } doublecalculate(doubleopnd1,charop,doubleopnd2) {switch(op){ case'+': returnopnd1+opnd2;case'-': returnopnd1-opnd2; case'*': returnopnd1*opnd2; case'/': if(opnd2! =0.0)returnopnd1/opnd2;elsereturn0.0; } return0.0; } : 操作数 no
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 报告