算术表达式与二叉树.docx

上传人:b****3 文档编号:26778812 上传时间:2023-06-22 格式:DOCX 页数:21 大小:186.06KB
下载 相关 举报
算术表达式与二叉树.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

算术表达式与二叉树

 

算术表达式与二叉树

一、系统开发的背景

为了方便进行基本的算术运算,减轻对数字较大的数操作时所带来的麻烦,及其在运算过程中错误的避免。

因此设计算术表达式与二叉树的程序来解决此问题。

二、系统分析与设计

(一)系统功能要求

由于一个表达式和一棵二叉树之间,存在着自然的对应关系。

遍写一个程序,实现基于二叉树表示的算术表达式的操作。

算术表达式内可以含有变量(a~z)、常量(0~9)和二元运算符(+,-,*,/,^(乘幂))。

具体实现以下操作:

1以字符序列的形式输入语法正确的前缀表达式并构造表达式。

2用带括弧的中缀表达式输出表达式。

3实现对变量V的赋值(V=c),变量的初值为0。

4对算术表达式E求值。

(二)系统模块结构设计

通过对系统功能的分析,基于二叉树表示的算术表达式的功能

如图

(1)所示。

 

图1:

基于二叉树表示的算术表达式的功能图

通过上图的功能分析,把整个系统划分为主要的两大个模块:

1、将语法正确的前缀表达式用二叉树的遍历转换成相应的遍历序列,必要时可以求出此二叉树的结点数及其树的深度。

该模块借助函数BiTreeCreate(BiTreeT)创建二叉树,voidPreorder(BiTreeT)先序遍历,voidInOrder(BiTreeT)中序遍历,voidPostOrder(BiTreeT)后序遍历,intSumleaf(BiTreeT)统计叶结点的数目,intDepth(BiTreeT)二叉树的深度6个函数联合来实现;

2、计算中序遍历所得的算术表达式的值。

其中先要将扫描得到的中缀表达式转换为后缀表达式,然后利用栈的初始化,进栈与取栈顶元素操作进行对后缀表达式进行计算。

该模块借助函数voidInitStack(SeqStack*S)初始化栈,intPushStack(SeqStack*S,chare)进栈,intGetTop(SeqStackS,char*e)取栈顶元素,voidTranslateExpress(charstr[],charexp[])中缀表达式转后缀表达式,floatComputeExpress(chara[])计算后缀表达式的值来实现;

三、系统的设计与实现

(一)二叉树的遍历

分析:

首先构建一棵二叉树,然后依次输出每个遍历的序列。

流程图如图2所示。

图2:

二叉树的遍历流程图

该模块的具体代码如下所示:

#include

#include

#defineMaxSize50

typedefstruct

{floatdata[MaxSize];

inttop;

}OpStack;

typedefstruct

{chardata[MaxSize];

inttop;

}SeqStack;

typedefstructBiTNode{

chardata;

structBiTNode*lchild,*rchild;

}BiTNode,*BiTree;

BiTreeCreate(BiTreeT)//用扩展先序遍历序列创建二叉树

{charch;

ch=getchar();

if(ch=='0')

T=NULL;

else{

T=newBiTNode;

T->data=ch;

T->lchild=Create(T->lchild);

T->rchild=Create(T->rchild);}

returnT;}

voidVisit(charch)//访问根节点

{printf("%c",ch);}

voidPreorder(BiTreeT)//先序遍历

{if(T==NULL)

return;

Visit(T->data);

Preorder(T->lchild);

Preorder(T->rchild);

}

voidInOrder(BiTreeT)//中序遍历

{if(T==NULL)

return;

InOrder(T->lchild);

Visit(T->data);

InOrder(T->rchild);

}

voidPostOrder(BiTreeT)//后序遍历

{if(T==NULL)

return;

PostOrder(T->lchild);

PostOrder(T->rchild);

Visit(T->data);

}

intSumleaf(BiTreeT)//统计叶结点的数目

{intsum=0,m,n;

if(T)

{if((!

T->lchild)&&(!

T->rchild))//该结点的左或右分支为空时

sum++;

m=Sumleaf(T->lchild);

sum=sum+m;

n=Sumleaf(T->rchild);

sum=sum+n;}

returnsum;

}

intDepth(BiTreeT)//二叉树的深度

{intdep=0,depl,depr;

if(!

T)dep=0;

else{

depl=Depth(T->lchild);

depr=Depth(T->rchild);

dep=1+(depl>depr?

depl:

depr);}

returndep;

}

voidmain()

{

BiTreeT;

intsum,k;

printf("请输入二叉树中的元素(以扩展先序遍历序列输入):

\n");

T=Create(T);

printf("先序遍历序列为:

");

Preorder(T);

printf("\n");

printf("中序遍历序列为:

");

InOrder(T);

printf("\n");

printf("后序遍历序列为:

");

PostOrder(T);

printf("\n");

sum=Sumleaf(T);

printf("叶结点的数目为:

%d\n",sum);

k=Depth(T);

printf("二叉树的深度为:

%d\n",k);

}

(二)算术表达式求值

分析:

首先初始化一个栈,然后对相关的数据元素及运算符进栈,之后中缀表达式转后缀表达式计算出后缀表达式的值。

流程图如图3所示。

图3:

算术表达式求值流程图

该模块的具体代码如下所示:

#include

#include

#include

#include

#include

#defineNULL0

#defineMaxSize50

typedefstruct

{floatdata[MaxSize];

inttop;

}OpStack;

typedefstruct

{chardata[MaxSize];

inttop;

}SeqStack;

voidInitStack(SeqStack*S)//初始化栈

{S->top=0;}

intStackEmpty(SeqStackS)//判断栈是否为空

{if(S.top==0)return1;

elsereturn0;}

intPushStack(SeqStack*S,chare)//进栈

{if(S->top>=MaxSize)

{printf("栈已满,不能进栈!

");

return0;

}else

{S->data[S->top]=e;

S->top++;

return1;}}

intPopStack(SeqStack*S,char*e)//删除栈顶元素

{if(S->top==0)

{printf("栈已空\n");

return0;

}else{S->top--;

*e=S->data[S->top];

return1;}}

intGetTop(SeqStackS,char*e)//取栈顶元素

{if(S.top<=0)

{printf("栈已空");return0;

}else{*e=S.data[S.top-1];

return1;}}

voidTranslateExpress(charstr[],charexp[])//把中缀表达式转换为后缀表达式

{SeqStackS;charch;chare;

inti=0,j=0;

InitStack(&S);

ch=str[i];i++;

while(ch!

='\0')//依次扫描中缀表达式

{switch(ch)

{case'(':

PushStack(&S,ch);break;

case')':

while(GetTop(S,&e)&&e!

='(')

{PopStack(&S,&e);

exp[j]=e;

j++;}

PopStack(&S,&e);break;

case'+':

case'-':

while(!

StackEmpty(S)&&GetTop(S,&e)&&e!

='(')

{PopStack(&S,&e);

exp[j]=e;

j++;}

PushStack(&S,ch);break;

case'^':

case'*':

case'/':

while(!

StackEmpty(S)&&GetTop(S,&e)&&e=='/'||e=='*'||e=='^')

{PopStack(&S,&e);

exp[j]=e;j++;}

PushStack(&S,ch);

break;//是空格就忽略

case'':

break;

default:

while(ch>='0'&&ch<='9')

{exp[j]=ch;j++;

ch=str[i];

i++;}

i--;exp[j]='';

j++;}

ch=str[i];

i++;}

while(!

StackEmpty(S))//将栈中剩余运算符出栈

{PopStack(&S,&e);

exp[j]=e;

j++;}exp[j]='\0';}

floatComputeExpress(chara[])//计算后缀表达式的值

{OpStackS;

inti=0;floatx1,x2,value;floatresult;

S.top=-1;

while(a[i]!

='\0')//依次扫描后缀表达式

{if(a[i]!

=''&&a[i]>='0'&&a[i]<='9')//如果是数字

{value=0;

while(a[i]!

='')//如果不是空格

{value=10*value+a[i]-'0';

i++;

}S.top++;

S.data[S.top]=value;//处理后进栈

}else//如果是运算符

{switch(a[i])

{case'+':

x1=S.data[S.top];S.top--;

x2=S.data[S.top];S.top--;

result=x1+x2;S.top++;

S.data[S.top]=result;break;

case'-':

x1=S.data[S.top];S.top--;

x2=S.data[S.top];S.top--;

result=x2-x1;S.top++;

S.data[S.top]=result;break;

case'*':

x1=S.data[S.top];S.top--;

x2=S.data[S.top];S.top--;

result=x1*x2;S.top++;

S.data[S.top]=result;break;

case'/':

x1=S.data[S.top];S.top--;

x2=S.data[S.top];S.top--;

result=x2/x1;S.top++;

S.data[S.top]=result;break;

case'^':

x1=S.data[S.top];S.top--;

x2=S.data[S.top];S.top--;

result=float(pow(x1,x2));S.top++;

S.data[S.top]=result;break;

}i++;

}}

if(S.top!

=-1)//如果栈不空,将结果出栈并返回

{result=S.data[S.top];

S.top--;if(S.top==-1)

returnresult;

else{printf("表达式错误");

exit(-1);}

}return0;}

voidmain()

{chara[MaxSize],b[MaxSize];

floatf;

printf("请输入一个算术表达式:

");

scanf("%s",&a);

printf("中缀表达式为:

%s\n",a);

TranslateExpress(a,b);

printf("后缀表达式为:

%s\n",b);

f=ComputeExpress(b);

printf("计算结果:

%f\n",f);}

四、系统测试

(一)测试二叉树遍历函数:

测试的结果如图4。

图4:

二叉树的遍历

(二)测试算术表达式求值函数:

测试的结果如图5,6。

图5

图6

五、总结

系统完成了对基本的数学算术运算的求值的功能。

系统不能对更高一级的复合表达式(如三角函数等)求值,是其不足之处。

我的收获是经过不断的查询相关的书籍与有关的资料,使得我对原本不熟的知识有了深刻的了解和认识。

也让我能够更加独立的去学习,提高了我的自主学习的能力。

六、附件(代码、部分图表)

(一)程序代码:

#include

#include//字符串函数

#include//功能:

分配字节的存储区,若内存不够返回0.

#include//tandardlibrary标准库函数头文件,stdlib.h里面定义了五种类型、一些宏和通用工具函数

#include//数学库函数

#defineNULL0

#defineMaxSize50

typedefstruct

{floatdata[MaxSize];

inttop;

}OpStack;//存放数字的栈

typedefstruct

{chardata[MaxSize];

inttop;

}SeqStack;//存放运算符的栈

typedefstructBiTNode{

chardata;

structBiTNode*lchild,*rchild;

}BiTNode,*BiTree;

BiTreeCreate(BiTreeT)//用扩展先序遍历序列创建二叉树

{charch;

ch=getchar();

if(ch=='0')

T=NULL;

else{T=newBiTNode;

T->data=ch;

T->lchild=Create(T->lchild);

T->rchild=Create(T->rchild);}

returnT;}

voidVisit(charch)//访问根节点

{printf("%c",ch);}

voidPreorder(BiTreeT)//先序遍历

{if(T==NULL)

return;

Visit(T->data);

Preorder(T->lchild);

Preorder(T->rchild);}

voidInOrder(BiTreeT)//中序遍历

{if(T==NULL)

return;

InOrder(T->lchild);

Visit(T->data);

InOrder(T->rchild);}

voidPostOrder(BiTreeT)//后序遍历

{if(T==NULL)

return;

PostOrder(T->lchild);

PostOrder(T->rchild);

Visit(T->data);}

intSumleaf(BiTreeT)//统计叶结点的数目

{intsum=0,m,n;

if(T){

if((!

T->lchild)&&(!

T->rchild))//该结点的左或右分支为空时

sum++;m=Sumleaf(T->lchild);

sum=sum+m;n=Sumleaf(T->rchild);

sum=sum+n;}

returnsum;}

intDepth(BiTreeT)//二叉树的深度

{intdep=0,depl,depr;

if(!

T)dep=0;

else{

depl=Depth(T->lchild);

depr=Depth(T->rchild);

dep=1+(depl>depr?

depl:

depr);}

returndep;}

voidInitStack(SeqStack*S)//初始化栈

{S->top=0;}

intStackEmpty(SeqStackS)//判断栈是否为空

{if(S.top==0)return1;

elsereturn0;}

intPushStack(SeqStack*S,chare)//进栈

{if(S->top>=MaxSize)

{printf("栈已满,不能进栈!

");

return0;}

else{S->data[S->top]=e;

S->top++;

return1;}}

intPopStack(SeqStack*S,char*e)//删除栈顶元素

{if(S->top==0){printf("栈已空\n");

return0;}else

{S->top--;*e=S->data[S->top];

return1;}}

intGetTop(SeqStackS,char*e)//取栈顶元素

{if(S.top<=0){printf("栈已空");

return0;}else{*e=S.data[S.top-1];

return1;}}

voidTranslateExpress(charstr[],charexp[])//把中缀表达式转换为后缀表达式

{SeqStackS;charch;chare;inti=0,j=0;InitStack(&S);

ch=str[i];i++;

while(ch!

='\0')//依次扫描中缀表达式

{switch(ch)

{case'(':

PushStack(&S,ch);break;

case')':

while(GetTop(S,&e)&&e!

='(')

{PopStack(&S,&e);

exp[j]=e;j++;}

PopStack(&S,&e);break;

case'+':

case'-':

while(!

StackEmpty(S)&&GetTop(S,&e)&&e!

='(')

{PopStack(&S,&e);

exp[j]=e;

j++;}

PushStack(&S,ch);break;

case'^':

case'*':

case'/':

while(!

StackEmpty(S)&&GetTop(S,&e)&&e=='/'||e=='*'||e=='^')

{PopStack(&S,&e);

exp[j]=e;

j++;}

PushStack(&S,ch);

break;//是空格就忽略

case'':

break;

default:

while(ch>='0'&&ch<='9')

{exp[j]=ch;j++;ch=str[i];

i++;}i--;

exp[j]='';

j++;}ch=str[i];

i++;}

while(!

StackEmpty(S))//将栈中剩余运算符出栈

{PopStack(&S,&e);

exp[j]=e;j++;}

exp[j]='\0';

}

floatComputeExpress(chara[])//计算后缀表达式的值

{OpStackS;inti=0;floatx1,x2,value;floatresult;S.top=-1;

while(a[i]!

='\0')//依次扫描后缀表达式

{if(a[i]!

=''&&a[i]>='0'&&a[i]<='9')//如果是数字

{value=0;while(a[i]!

='')//如果不是空格

{value=10*value+a[i]-'0';i++;}//相当于一个循环,把数组a[]值赋给value.

S.top++;

S.data[S.top]=value;//处理后进栈

}else//如果是运算符

{switch(a[i])

{case'+':

x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;

result=x1+x2;S.top++;

S.data[S.top]=result;break;

case'-':

x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;

result=x2-x1;S.top++;

S.data[S.top]=result;break;

case'*':

x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;

result=x1*x2;

S.top++;

S.data[S.top]=result;break;

case'/':

x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;

result=x2/x1;S.top++;

S.data[S.top]=result;break;

case'^':

x1=S.data[S.top];S.top--;x2=S.data[S.top];S.top--;

result=float(pow(x1

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

当前位置:首页 > 求职职场 > 职业规划

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

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