数据结构实验报告.docx

上传人:b****5 文档编号:4535728 上传时间:2022-12-01 格式:DOCX 页数:21 大小:161.81KB
下载 相关 举报
数据结构实验报告.docx_第1页
第1页 / 共21页
数据结构实验报告.docx_第2页
第2页 / 共21页
数据结构实验报告.docx_第3页
第3页 / 共21页
数据结构实验报告.docx_第4页
第4页 / 共21页
数据结构实验报告.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

数据结构实验报告.docx

《数据结构实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告.docx(21页珍藏版)》请在冰豆网上搜索。

数据结构实验报告.docx

数据结构实验报告

课程设计实验报告

实验名称:

表达式类型的实现

编译环境:

硬件:

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

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 教学研究 > 教学计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1