题目设计一个程序实现基于二叉树表示的算术表达式的操作文档格式.docx
- 文档编号:18812909
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:34
- 大小:231.37KB
题目设计一个程序实现基于二叉树表示的算术表达式的操作文档格式.docx
《题目设计一个程序实现基于二叉树表示的算术表达式的操作文档格式.docx》由会员分享,可在线阅读,更多相关《题目设计一个程序实现基于二叉树表示的算术表达式的操作文档格式.docx(34页珍藏版)》请在冰豆网上搜索。
//存放变量名
intval;
//存放变量的值,初始值为0
}vary;
//存放变量
intordina;
//存放常量值
};
structExpNode*lchild,*rchild;
/*左右孩子指针*/
}*ExpTree;
/*二叉树的二叉链表存储表示*/
基本操作:
intRandom(intnMin,intnMax);
//返回nMin到nMax之间的随机数
voidFindVary(char*c,char*e);
//找出表达式中的变量
StatusArrayCreateExp(ExpTree&
E,char*ch,int&
i);
//从ch数组中读取字符串,构造表达式
voidCreateExp(ExpTree&
i);
//StatusInputCreateExp(ExpTree&
E);
//从键盘先序输入来构造表达式树T
StatusVisit(ExpTreee);
//输出e的内容
voidInorderExp(ExpTreeE,Status(*Visit)(ExpTreee));
//输出中序表达式用带括号的中缀表示式输出
StatusAssign(ExpTreeE,charv,floatc);
//对表达式内的所有v,赋值c
floatValue(ExpTreeE);
//计算表达式的值
ExpTreeCompound(charp,ExpTreee1,ExpTreee2);
//5.构造一个新的复合表达式(E1)P(E2)
StatusDiff(ExpTree&
E,charV);
//求表达式E对变量V的导数
voidMergeConst(ExpTreeE);
//合并表达式种所有常数运算
StatusPreOrderTraverse(ExpTreeE,Status(*Visit)(ExpTreee));
//波兰式输出
StatusPostOrderTraverse(ExpTreeE,Status(*Visit)(ExpTreee));
//逆波兰式输出
2)、队列
typedefcharQElemType;
typedefstructQNode
QElemTypedata;
structQNode*next;
}QNode,*QuePtr;
typedefstruct
QuePtrfront;
QuePtrrear;
}Queue;
StatusInitQueue(Queue&
Q);
//构造一个空队列
StatusDestroyQueue(Queue&
//销毁队列
StatusQueueEmpty(QueueQ);
//判空
StatusEnQueue(Queue&
Q,QElemTypee);
//插入元素e为Q的新的队尾元素
StatusDeQueue(Queue&
Q,QElemType&
e);
//删除队头元素,用e返回其值,并返回OK,否则返回ERROR;
3)、栈
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
StatusInitStack(SqStack&
S);
StatusStackEmpty(SqStackS);
StatusPush(SqStack&
S,SElemTypee);
StatusPop(SqStack&
S,SElemType&
SElemTypeTop(SqStackS);
6、主程序:
voidmain()
while
(1)
{接受命令
处理命令;
Switch()
case:
1.以数组形式输入前缀表示式函数构造表达式.
2.以字符序列输入前缀表示式函数构造表达式.
3.实现对变量V的赋值(V=c).
4.对算术表达式E求值.\n"
);
5.构造一个新的复合表示式(E1)P(E2).
6.求偏导函数Diff(E,V)
7.对三角函数的测试.
8.常数合并.
0.结束
}
三、详细设计
1、存放表达式的结构类型,是以二叉树为基本原型。
我原来是直接用二叉树的存储结构的,后来发现受到这个结构类型的很大限制,受到广义表存储结构的启发,就自己设计了这样一个存储类型。
下面分析这个存储结构:
(1)、用ElemTagtag;
来标记是运算符,变量,常量。
用枚举类型定义typedefenum{OPER,VAR,ORD}ElemTag,可以区分是运算符,变量,常量。
(2)、用字符串charexpr[4];
来存放运算符名,我先预定存放三个字符的运算符名(最后一个char用来存放’\0’),这样运算符不仅可以是'
+'
,'
-'
*'
,'
/'
^'
,还可以是’sin’,’cos’,’tan’。
如果觉得三个字符不够,可以扩展。
(3)、struct{charvar;
//存放变量名floatval;
//存放变量的值,初始为0}vary;
//存放变量。
这样在变量赋值后,还可以保存着变量名。
可以用作如公式一样,重复赋值使用。
(4)、使用intordina;
来存放常量值。
这样赋值时,就扩大了赋值范围,可以是一个整形的范围,大大扩大了本程序的使用范围。
但需要在赋值时使用,在输入时,还是得用0-9,这也是本程序的缺陷,有待改进。
2、队列。
3、栈
4、主函数和其他主要函数
1)、访问函数(输出函数)
StatusVisit(ExpTreee)
intm,n[5];
if(e->
tag==OPER)//运算符
printf("
%s"
e->
expr);
elseif(e->
tag==VAR)//变量
{
if(!
e->
vary.val)//变量的值是0
%c"
vary.var);
//输出变量名
else
%0.4f"
vary.val);
//输出变量的值
}
else//常量
if(e->
ordina>
=0)//正数
%d"
ordina);
(%d)"
//负数,输出时加括号
returnOK;
2)、构造表达式
i)
if(ch[i])
(E=(ExpTree)malloc(sizeof(ExpNode))))
returnERROR;
if(ch[i]=='
s'
&
&
ch[i+1]=='
i'
ch[i+2]=='
n'
||//sin
ch[i]=='
S'
I'
N'
||
c'
o'
||//cos
C'
O'
t'
a'
||//tan
T'
A'
)
{
E->
tag=OPER;
expr[0]=ch[i];
E->
expr[1]=ch[++i];
expr[2]=ch[++i];
expr[3]='
\0'
;
ArrayCreateExp(E->
rchild,ch,++i);
//只建右子树
lchild=NULL;
//左子树为空
returnOK;
}
elseif(ch[i]>
='
0'
ch[i]<
9'
)//数字
tag=ORD;
ordina=ch[i]-'
z'
)//变量
tag=VAR;
vary.var=ch[i];
vary.val=0;
elseif(ch[i]=='
||ch[i]=='
)//运算符
expr[1]='
tag)//E是运算符
lchild,ch,++i);
rchild=NULL;
3)、带括号的中缀表示式输出
voidInorderExp(ExpTreeE,Status(*Visit)(ExpTreee))
intbracket;
if(E)
if(E->
lchild)
bracket=precede(E,E->
lchild);
//比较双亲与左孩子运算符优先级
if(bracket>
0)//左孩子优先级低
printf("
("
InorderExp(E->
lchild,Visit);
0)
)"
Visit(E);
rchild)
rchild);
//比较双亲与右孩子运算符优先级
=0)//右孩子优先级低
rchild,Visit);
=0)
4)、计算表达式的值
floatValue(ExpTreeE)
floatlv,rv,value=0;
tag==VAR)//是变量
return(E->
tag==ORD)
lchild)lv=Value(E->
rv=Value(E->
switch(E->
expr[0])
case'
:
value=lv+rv;
break;
value=lv-rv;
value=lv*rv;
if(rv)value=lv/rv;
elseexit(0);
break;
value=power(lv,rv);
case'
value=sin(rv);
//sin
value=tan(rv);
//tan
if(E->
expr[2]=='
||E->
)//cos
{value=cos(rv);
break;
}
return(value);
5)、合并常数
voidMergeConst(ExpTreeE)
//合并表达式中所有常数运算
if(!
lchild&
!
rchild)return;
//叶子
if(E->
tag==OPER&
rchild&
lchild->
tag==ORD&
rchild->
E->
case'
ordina=E->
ordina*E->
ordina;
break;
ordina/E->
ordina=power(E->
ordina,E->
ordina+E->
ordina-E->
free(E->
else
MergeConst(E->
5、构造的表达式如图
算术表达式前缀表示:
*+ab-cd
中缀带括号表示:
(a+b)*(c-d)
四、调试分析
1、调试过程中遇到了许多问题,下面举几个例子。
(1)赋值出错处理
在调试赋值函数时发生了“赋值失败的情况”
修改前的函数:
voidFindVary(char*c,char*e)
inti=-1,j=0;
while(e[++i])
if(e[i]>
e[i]<
Z'
||e[i]>
){
i+=2;
continue;
else
c[j++]=e[i];
c[j]=0;
调试出现下面的情况
出现了两次了对X的赋值,原因是我在编写voidFindVary(char*c,ch
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 题目 设计 一个 程序 实现 基于 二叉 表示 算术 表达式 操作