二叉树数据结构课设说明书.docx
- 文档编号:9370590
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:33
- 大小:509.46KB
二叉树数据结构课设说明书.docx
《二叉树数据结构课设说明书.docx》由会员分享,可在线阅读,更多相关《二叉树数据结构课设说明书.docx(33页珍藏版)》请在冰豆网上搜索。
二叉树数据结构课设说明书
*******************
实践教学
*******************
兰州理工大学
计算机与通信学院
2012年春季学期
算法与数据结构课程设计
题目:
二叉树操作
专业班级:
软件工程基地班
姓名:
学号:
10240445
指导教师:
王旭阳
成绩:
目录
摘要1
1.采用类c语言定义相关的数据类型2
2.各模块的伪码算法2
3.函数的调用关系图8
4.调试分析9
5.测试结果9
6.源程序(带注释)15
总结30
参考文献31
致谢32
附件Ⅰ任务一源程序代码33
摘要
该设计要求学生设计程序,实现二叉树的相关操作。
通过该题目的设计过程,可以加深理解二叉树的逻辑结构、存储结构,掌握二叉树上基本运算的实现,进一步理解和熟练掌握课本中所学的各种数据结构,学会如何把学到的知识用于解决实际问题,培养学生的动手能力。
关键词:
逻辑结构;存储结构;基本运算;二叉链表存储结构;
1.采用类c语言定义相关的数据类型
定义二叉树二叉链表结构
structtree
{
intdata;//结点存储的数据
intlevel;//该结点所在层数(根结点为一层)
structtree*lchild;//指向该结点左孩子结点的指针
structtree*rchild;//指向该结点右孩子结点的指针
};
2.各模块的伪码算法
计算树的高度
intCountHigh(structtree*T)
{intlhigh=0;//存储以T指向的结点为根结点的左子树的高度
intrhigh=0;//存储以T指向的结点为根结点的右子树的高度
if(T->lchild==NULL&&T->rchild==NULL)//若该子树就一个根结点
returnT->level;
else{if(T->lchild!
=NULL)//若该子树有左子树
lhigh=CountHigh(T->lchild);//计算左子树高度
if(T->rchild!
=NULL)//若该子树有右子树
rhigh=CountHigh(T->rchild);//计算右子树高度
if(lhigh>rhigh)//返回左右子树高度最大值
returnlhigh;elsereturnrhigh;}}
2.计算分支结点数
intCountNleaf(structtree*T)
{intlnleaf=0;//存储左子树分支结点数
intrnleaf=0;//存储右子树分支结点数
if(T->lchild==NULL&&T->rchild==NULL)//若该子树就一个根结点
return0;else{if(T->lchild!
=NULL)//若有左子树
lnleaf=CountNleaf(T->lchild);//计算左子树分支结点数
if(T->rchild!
=NULL)//若有右子树
rnleaf=CountNleaf(T->rchild);//计算右子树分支结点数
return(1+lnleaf+rnleaf);//返回分支结点数}}
3计算叶子节点数
intCountLeaf(structtree*T){
intlleaf=0;//存储左子树叶子结点数
intrleaf=0;//存储右子树叶子结点数
if(T->lchild==NULL&&T->rchild==NULL)//若该子树就一个根结点
return1;else{if(T->lchild!
=NULL)//若有左子树
lleaf=CountLeaf(T->lchild);//计算左子树叶子结点数
if(T->rchild!
=NULL)//若有右子树
rleaf=CountLeaf(T->rchild);//计算右子树叶子结点数
return(lleaf+rleaf);//返回左右子树叶子结点数总和}}
4.在确定位置增加一个新的叶子结点
voidAddPoint(structtree*T){intgoal;//存储新叶子结点元素
intpgoal;//存储新叶子结点的父结点元素intwhether;//判断插入结果
printf("请输入新结点的数据元素:
");scanf("%d",&goal);
printf("请输入新结点的父结点中的数据元素:
");scanf("%d",&pgoal);
whether=Add(T,pgoal,goal);//递归查找父结点并进行插入操作
switch(whether)//判断插入结果
{case-1:
printf("无法插入结点,因为父结点已有两个孩子结点!
\n");break;
case0:
printf("无法插入该结点,因为树中不存在输入的父结点!
\n");break;
case1:
{printf("结点插入成功!
\n");PrintTree(T);}break;
default:
break;}}
5.递归查找确定的叶子结点并删除
intDelete(structtree**T,intgoal){intwhether;
if((*T)->data==goal)//若该结点就为要删除的结点
{if((*T)->lchild==NULL&&(*T)->rchild==NULL)//若该结点为叶子结点
{free(*T);*T=NULL;return1;}
else//若该结点不是叶子结点{return-1;}}
else//若该结点不是要删除的结点
{if((*T)->lchild==NULL&&(*T)->rchild==NULL)//若该结点为叶子结点
return0;
else//若该结点不是叶子结点{if((*T)->lchild!
=NULL)//若有左子树
{whether=Delete(&((*T)->lchild),goal);//在其左子树中查找要删除的结点
if(whether==0&&(*T)->rchild!
=NULL)//若左子树中没找到要删除的结点且存在右子树
returnDelete(&((*T)->rchild),goal);//在其右子树中查找要删除的结点
else//若右子树不存在returnwhether;}
else//若左子树不存在
returnDelete(&((*T)->rchild),goal);//在其右子树中查找要删除的结点}}}
6.递归交换左右子树
voidExchange(structtree*T){structtree*changePtr;
if(T!
=NULL)//若该根结点存在{changePtr=T->lchild;
T->lchild=T->rchild;
T->rchild=changePtr;//交换该根结点的左右子树
Exchange(T->lchild);//对其左子树进行所有左右子树交换
Exchange(T->rchild);//对其右子树进行所有左右子树交换}}
7.层序遍历该树
voidLevelTravel(structtree*T){inti;
structtree*t[100];//将树的每个结点按一定编号存储到一维数组中
printf("层序遍历为:
\n");
for(i=0;i<100;i++)t[i]=NULL;if(T!
=NULL)
t[1]=T;//根结点编号下标为1
for(i=1;i<100;i++)if(t[i]!
=NULL)
{if(t[i]->lchild!
=NULL)//若有左子树
t[2*i]=t[i]->lchild;//存储左子树根结点
if(t[i]->rchild!
=NULL)//若有右子树
t[2*i+1]=t[i]->rchild;//存储右子树根结点
printf("%-3d",t[i]->data);//按数组顺序打印出各结点元素}printf("\n");}
8.先序遍历
voidPreTravel(structtree*T){if(T!
=NULL)//若根结点存在
{printf("%-3d",T->data);//打印根结点元素
PreTravel(T->lchild);//遍历左子树PreTravel(T->rchild);//遍历右子树}}
9.中序遍历
voidMidTravel(structtree*T){if(T!
=NULL)//若根结点存在
{MidTravel(T->lchild);//遍历左子树
printf("%-3d",T->data);//打印根结点元MidTravel(T->rchild);//遍历右子树}}
10.后序遍历
voidAfterTravel(structtree*T){if(T!
=NULL)//若根结点存在
{AfterTravel(T->lchild);//遍历左子树
AfterTravel(T->rchild);//遍历右子树printf("%-3d",T->data);//打印根结点元素}
}
3.函数的调用关系图
4.调试分析
a、调试中遇到的问题及对问题的解决方法
1、输出的运行界面不整齐,例如“*”在编写程序的时候输入不整齐,运行出来的界面就不好看。
2、在使用解释符号时应该注意“//”,不适合于TC的环境,要用“/**/”。
3、函数的调用不正确。
解决方法:
当在一个函数中要调用另一个函数时,必须在调用函数的函数块中对被调用函数进行类型的声明
b、算法的时间复杂度和空间复杂度
时间复杂度:
T(n)=O(n);
空间复杂度:
S(n)=O(f(n));
5.测试结果
1.创建二叉树
2.计算二叉树的高度,分支节点数以及叶子节点数
3.在指定位置插入数据元素
4.删除指定位置数据元素
5.交换左右子树
6.层序遍历
7.先序遍历
8.中序遍历
9.后序遍历
10.结束
6.源程序(带注释)
#include
#include
//将树的结点定义为结构
structtree{intdata;//结点存储的数据
intlevel;//该结点所在层数(根结点为一层)
structtree*lchild;//指向该结点左孩子结点的指针
structtree*rchild;//指向该结点右孩子结点的指针}
intpretotal=0;//遍历先序序列的下标
structtree*GetSequence();//读取先序序列和中序序列
structtree*CreateTree(intstart,intend,inttotal,intpredata[],
intmiddata[]);//创建树
intFindElem(intmiddata[],intgoaldata,inttotal);//查找goaldata在middat中的下标
intGetChoose();//读取用户选择的操作
voidCountTree(structtree*T);//对树进行计算操作
intCountHigh(structtree*T);//计算树的高度
intCountNleaf(structtree*T);//计算树的分支结点数
intCountLeaf(structtree*T);//计算树的叶子结点数
voidPointTree(structtree*T);//增加或删除叶子结点
voidAddPoint(structtree*T);//增加叶子结点
intAdd(structtree*T,intpgoal,intgoal);//递归查找叶子结点增加的位置
voidDeletePoint(structtree*T);//删除叶子结点
intDelete(structtree**T,intgoal);//递归查找叶子结点删除的位置
voidExchangeTree(structtree*T);//交换所有结点的左右子树
voidExchange(structtree*T);//递归调换所有结点的左右子树
voidTravelTree(structtree*T);//遍历树
voidLevelTravel(structtree*T);//层序遍历该树
voidPreTravel(structtree*T);//先序遍历该树
voidMidTravel(structtree*T);//中序遍历该树
voidAfterTravel(structtree*T);//后序遍历该树
voidPrintTree(structtree*T);//按二叉树的格式打印该树
intf(intn);//计算2的n次方
voidFreeTree(structtree*T);//程序结束后释放动态生成的结点
main(){intchoose=-1;//存储用户选择操作的序号
structtree*headPtr=NULL;//指向树根结点的指针
headPtr=GetSequence();//通过先序序列和中序序列建立一棵二叉树并用headPtr指向该树的根结点
PrintTree(headPtr);//按树的格式打印该二叉树
while(choose){choose=GetChoose();//由用户输入选择操作的序号
switch(choose){case1:
CountTree(headPtr);break;//计算二叉树高度、分支结点数及叶子结点数
case2:
PointTree(headPtr);break;//增加或删除叶子结点
case3:
ExchangeTree(headPtr);break;//所有结点左右子树交换
case4:
TravelTree(headPtr);break;//遍历default:
break;}}
system("CLS");printf("谢谢使用!
再见!
!
!
\n");
FreeTree(headPtr);//释放动态申请的结点system("pause");}
/*函数功能:
读取输入的树的先序序列和中序序列,传递参数:
无,返回值:
指向由先序序列和中序序列确定的二叉树的根结点指针*/
structtree*GetSequence(){intt1=0;//统计先序序列元素个数
intt2=0;//统计中序序列元素个数inttotal;//统计树结点个数
intmid;//存储先序序列第一个元素在中序序列中的下标
intwhether=1;//判断是否存在该树charch;//判断序列结束符
intpredata[100];//存储先序序列intmiddata[100];//存储中序序列
structtree*headPtr;//指向由先序序列和中序序列确定的二叉树的根结点
while(whether)
{printf("************二叉树操作**************\n”);
printf("\n\n");printf("请输入先序序列(不同结点数据用“空格”隔开,以“回车”作为序列结束符):
\n");
ch='';while(ch!
='\n')//读取先序序列{scanf("%d",&predata[t1]);
t1++;ch=getchar();}printf("请输入中序序列(不同结点数据用“空格”隔开,以“回车”作为序列结束符):
\n");
ch='';while(ch!
='\n')//读取中序序列{scanf("%d",&middata[t2]);
t2++;ch=getchar();}if(t1==t2)//若先序序列中序序列元素个数相等
{total=t1;whether=0;}
elseprintf("两个序列结点个数不同,不能构成树,请重新输入!
!
!
\n");
printf("****************************************\n");}
headPtr=malloc(sizeof(structtree));//动态生成根结点
headPtr->data=predata[0];headPtr->lchild=NULL;
headPtr->rchild=NULL;
mid=FindElem(middata,predata[pretotal],total);//查找根结点元素在中序序列中的下标
pretotal++;//遍历先序序列
headPtr->lchild=CreateTree(0,mid-1,total,predata,middata);//创建根结点的左子树
headPtr->rchild=CreateTree(mid+1,total-1,total,predata,middata);//创建根结点的右子树
returnheadPtr;//返回根结点指针}
/*函数功能:
根据先序序列和中序序列递归建立每棵子树,传递参数:
中序序列起始下标start,终止下标end,结点总个数total,先序序列predata,中序序列middata,返回值:
根结点指针*/
structtree*CreateTree(intstart,intend,inttotal,intpredata[],intmiddata[])
{intmid;structtree*T;if(start<=end)//若存在该子树
{T=malloc(sizeof(structtree));//生成该子树的根结点
T->data=predata[pretotal];T->lchild=NULL;
T->rchild=NULL;
mid=FindElem(middata,predata[pretotal],total);//查找该子树根结点在中序序列中的下标
pretotal++;//遍历先序序列
T->lchild=CreateTree(start,mid-1,total,predata,middata);//创建该子树的左子树
T->rchild=CreateTree(mid+1,end,total,predata,middata);//创建该子树的右子树
returnT;//返回根结点指针}else//若不存在该子树returnNULL;}
/*函数功能:
查找确定元素在中序序列中的下标,传递参数:
中序序列middata,确定元素goaldata,结点总个数total,返回值:
该确定元素在中序序列中的下标*/
intFindElem(intmiddata[],intgoaldata,inttotal)
{inti=0;while(middata[i]!
=goaldata)
i++;returni;}
/*函数功能:
读取用户输入的操作序号,传递参数:
无,返回值:
用户输入的操作序号*/
intGetChoose(){intchoose;
printf("*********************************************\n");
printf("您可以选择进行的操作:
\n");
printf("1、计算(二叉树的高度、分支结点数以及叶子结点数);\n");
printf("2、增删结点操作;\n");
printf("3、交换左右子树操作;\n");
printf("4、遍历操作\n");printf("0、退出\n");
printf("*********************************************\n");
printf("请输入要进行操作的序号:
");scanf("%d",&choose);
while(!
(choose>=0&&choose<=4))
{printf("输入无效!
请重新输入:
");scanf("%d",&choose);}
returnchoose;}
/*函数功能:
计算树的相关信息(包括树的高度、分支结点数、叶子结点数),传递参数:
指向根结点的指针,返回值:
无*/
voidCountTree(structtree*T){inthigh=0;//存储树的高度
intnleaf=0;//存储分支结点数intleaf=0;//存储叶子结点数
high=CountHigh(T);//计算树的高度
nleaf=CountNleaf(T);//计算分支结点数
leaf=CountLeaf(T);//计算叶子结点数
printf("\n******************************************\n");
printf("树的高度为:
%d\n",high);printf("分支结点数为:
%d\n",nleaf);
printf("叶子结点数为:
%d\n",leaf);
printf("******************************************\n\n");}
/*函数功能:
计算树的高度,传递参数:
根结点指针,返回值:
以T指向的结点为根结点的子树的高度*/
intCountHigh(structtree*T)
{intlhigh=0;//存储以T指向的结点为根结点的左子树的高度
intrhigh=0;//存储以T指向的结点为根结点的右子树的高度
if(T->lchild==NULL&&T->rchild==NULL)//就一个根结点
returnT->level;else{if(T->lchild!
=NULL)//若该子树有左子树
lhigh=CountHigh(T->lchild);//计算左子树高度
if(T->rchild!
=NULL)//若该子树有右子树
rhigh=CountHigh(T->rchil
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 二叉 数据结构 说明书