树综合操作数据结构课程设计.docx
《树综合操作数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《树综合操作数据结构课程设计.docx(20页珍藏版)》请在冰豆网上搜索。
树综合操作数据结构课程设计
数据结构
课程设计(论文)
树的综合操作
院(系)名称
专业班级
学号
学生姓名
指导教师
起止时间:
2014.12.29—2015.1.9
课程设计(论文)任务及评语
院(系):
电子与信息工程学院教研室:
软件工程
学号
学生姓名
专业班级
课程设计(论文)题目
树的综合操作
课程设计(论文)任务
任务要求:
树的综合操作实现以下几个功能:
(1)创建二叉树的存储结构并保存;
(2)非递归实现中序遍历二叉树(3)非递归实现先序遍历二叉树。
(4)递归实现层次遍历二叉树;(5)求出二叉树的叶子结点数和层次数。
技术要求:
1、数据的逻辑结构采用树形结构,物理结构采用链式存储结构(二叉链表)。
2、软件能正常运行,界面清晰,操作要简单。
3、系统要有主界面设计,调用各个功能项。
4、采用ViscalC++编写代码,可读性强。
5、数据类型用typedef定义。
指导教师评语及成绩
平时成绩:
答辩成绩:
论文成绩:
总成绩:
指导教师签字:
年月日
注:
平时成绩占20%,答辩成绩占40%,论文成绩占40%。
摘要
这次的课题主要是创建二叉树的存储结构并保存,通过这一过程了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力并提高综合运用所学的理论知识和方法独立分析和解决问题的能力
主要解决以下问题
①创建二叉树的存储结构并保存;
②非递归实现中序遍历二叉树;
③非递归实现先序遍历二叉树;
④递归实现层次遍历二叉树;
⑤求出二叉树的叶子节点数和层次树;
关键词:
存储结构;二叉树;C++
第1章绪论
1.1系统的开发背景
二叉树结构是C语言中的难点,但是近年来二叉树的应用越发的广泛,实用性越来越强。
为了应对日新月异的时代变化,我参与了这个课题来提高自己对二叉树的掌握
1.2开发工具及语言
本系统使用ViscalC++语言开发,主界面清晰显示所有功能项,使用简单。
各个功能项均定义一个函数来实现,在主函数中调用各个子函数实现不同的功能。
第2章概要设计
2.1模块划分
1)题目应实现的具体功能;
①创建二叉树的存储结构并保存;
②非递归实现中序遍历二叉树;
③非递归实现先序遍历二叉树;
④递归实现层次遍历二叉树;
⑤求出二叉树的叶子节点数和层次树;
2.2数据结构的选择
系统数据的逻辑结构采用树形结构,物理结构采用链式存储结构(二叉链表)。
存储结构定义如下:
typedefstructlnode
{chardata;
structlnode*lchild,*rchild;
}lnode,*tree;
第3章系统详细设计与编码
3.1完整的源程序
#include
#include
#include
#defineOK1
#defineERROR0
#defineOVERFLOW-2
#defineMaxSize100
typedefcharTElemType;
typedefintStatus;
//二叉树的链式存储结构
typedefstructBiTNode{
TElemTypedata;
structBiTNode*lchild,*rchild;
}BiTNode,*BiTree;
//栈的链式存储结构
typedefstructLNode
{
BiTreedata;
structLNode*next;
}LNode,*LinkList;
//进栈
StatusPush(LinkList&S,BiTreeT)
{
LinkListstack;
stack=(LinkList)malloc(sizeof(LNode));//分配空间
stack->data=T;
stack->next=S->next;//进栈
S->next=stack;
returnOK;
}//Push
//出栈
StatusPop(LinkList&S,BiTree&T)
{
LinkListstack;
stack=S->next;//出栈
S->next=stack->next;//栈顶指向下个元素
T=stack->data;
returnOK;
}//Pop
//是否为空栈
StatusStackEmpty(LinkListS)
{
if(S->next==NULL)
returnOK;
else
returnERROR;
}
//以先序次序建立二叉树
StatusCreatBiTree(BiTree&T)
{
TElemTypech;
cin>>ch;
if(ch=='#')T=NULL;
else{
if(!
(T=(BiTree)malloc(sizeof(BiTNode))))exit(OVERFLOW);//分配存储空间
T->data=ch;//生成根节点
CreatBiTree(T->lchild);//生成左子树
CreatBiTree(T->rchild);//生成右子树
}
returnOK;//创建成功
}//CreatBiTree
//非递归中序访问二叉树
BiTreeGoFarLeft(BiTreeT,LinkList&S)//指到二叉树最左边结点
{
if(!
T)returnNULL;
while(T->lchild)
{
Push(S,T);//结点进栈
T=T->lchild;
}
returnT;//返回树头结点
}
voidInorder_I(BiTreeT)
{
BiTreet;
LinkListS;
S=(LinkList)malloc(sizeof(LNode));
S->next=NULL;
t=GoFarLeft(T,S);//找到最左下的结点
while(t)
{
cout<data<<"";
if(t->rchild)
t=GoFarLeft(t->rchild,S);
elseif(!
StackEmpty(S))//栈空表明遍历结束
Pop(S,t);
elset=NULL;
}//while
cout<}//Inorder_I
//先序非递归遍历算法1
voidPreOrder1(BiTreeT)
{
BiTreeStack[MaxSize],p;//定义栈
inttop=0;
p=T;
while(p!
=NULL||top>0)
{
while(p!
=NULL)
{
cout<data<<"";//输出结点data
Stack[top]=p;//左树进栈
top++;
p=p->lchild;
}
if(top>0)
{
top--;
p=Stack[top];
p=p->rchild;
}
}
cout<}
//先序遍历非递归算法2
voidPreOrder2(BiTreeb)
{
LinkListstack;
BiTreep;
p=(BiTree)malloc(sizeof(BiTree));
stack=(LinkList)malloc(sizeof(LinkList));
stack->next=NULL;
Push(stack,b);//二叉树头结点进栈
while(!
StackEmpty(stack))//是否为空
{
Pop(stack,p);//出栈
while(p)
{
cout<data<<"";//输出当前指向结点
if(p->rchild)Push(stack,p->rchild);//访问右指点
p=p->lchild;
}
}
cout<}
//后序非递归遍历
voidPostOrder(BiTreeT)
{
BiTreestack[MaxSize],p;
inttop=0;
p=T;
do
{
while(p!
=NULL)
{
stack[++top]=p;
p=p->lchild;
}
while(top>0&&stack[top]->rchild==p)
{
p=stack[top--];//栈顶结点出栈
cout<data<<"";//访问p所指向的结点
}
if(top>0)
p=stack[top]->rchild;//开始遍历右子树
}while(top>0);
cout<}
//计算叶子结点的个数
voidCountLeaf(BiTreeT,int&count)
{
if(T)
{
if((!
T->lchild)&&(!
T->rchild))
count++;
CountLeaf(T->lchild,count);//左子树叶子个数
CountLeaf(T->rchild,count);//右子树叶子个数
}
}//CountLeaf
//计算双结点个数
voidCountParent(BiTreeT,int&count)
{
if(T)
{
if(T->lchild&&T->rchild)
count++;
CountParent(T->lchild,count);//左子树双结点个数
CountParent(T->rchild,count);//右子树双结点个数
}
}
//计算二叉树结点个数
voidCount(BiTreeT,int&count)
{
if(T)
{
Count(T->lchild,count);
Count(T->rchild,count);
count++;//结点个数
}
}
//单结点个数
voidCountChild(BiTreeT,int&count)
{
if(T)
{
if((T->lchild&&(!
T->rchild))||(T->rchild&&(!
T->lchild)))
count++;
CountChild(T->lchild,count);//左子树单结点个数
CountChild(T->rchild,count);//右子树单结点个数
}
}
//计算树的高度
intDepth(BiTreeT)
{intdepthval,depthLeft,depthRight;
if(!
T)depthval=0;
else
{depthLeft=Depth(T->lchild);//左子树高度
depthRight=Depth(T->rchild);//右子树高度
depthval=1+(depthLeft>depthRight?
depthLeft:
depthRight);//取高度最高
}
returndepthval;//返回
}
//计算任意结点所在的层次
intNodeLevel(BiTreeT,TElemType&p,int&count)
{
if(T==NULL)
return0;
if(T->data==p)
return1;
if(NodeLevel(T->lchild,p,count)||(NodeLevel(T->rchild,p,count)))
{
count++;
return1;
}
return0;
}
//主函数
voidmain()
{
charflag;
cout<<"操作选项"<cout<<"1,非递归打印二叉树(前序,中序,后序)"<cout<<"2,计算二叉树的结点总数,双孩子个数,单孩子结点数,叶子结点数目"<cout<<"3,计算二叉树的高度"<cout<<"4,判断结点的层次"<do
{
intitem;
cout<<"请输入要操作的选项(1--6):
";
cin>>item;
switch(item)
{
case1:
{
BiTreeT;
cout<<"请输入要建立的二叉树,以'#'表示空树"<CreatBiTree(T);
cout<<"先序非递归输出二叉树(两种算法)"<cout<<"算法1:
"<PreOrder1(T);
cout<<"算法2:
"<PreOrder2(T);
cout<<"中序非递归输出二叉树"<Inorder_I(T);
cout<<"后序非递归输出二叉树"<PostOrder(T);
cout<cout<<"是否继续操作?
(y/n)"<cin>>flag;
break;
}
case2:
{
BiTreeT;
intnodeCount=0,leafCount=0,childCount=0,parentCount=0;
cout<<"请输入要建立的二叉树,以'#'表示空树"<CreatBiTree(T);
Count(T,nodeCount);
CountParent(T,parentCount);
CountChild(T,childCount);
CountLeaf(T,leafCount);
cout<<"结点总数目为:
"<cout<<"双孩子结点数目:
"<cout<<"单孩子结点数目:
"<cout<<"叶子结点数目:
"<cout<<"是否继续操作?
(y/n)"<cin>>flag;
break;
}
case3:
{
BiTreeT;
cout<<"请输入要建立的二叉树,以'#'表示空树"<CreatBiTree(T);
cout<<"该二叉树的高度为:
"<cout<<"是否继续操作?
(y/n)"<cin>>flag;
break;
}
case4:
{
BiTreeT;
intn=0;
charch;
cout<<"请输入要建立的二叉树,以'#'表示空树"<CreatBiTree(T);
cout<<"请输入要查询的结点:
";
cin>>ch;
if(T==NULL)
cout<<"空树"<else
NodeLevel(T,ch,n);
cout<<"结点的层次为:
";
cout<cout<<"是否继续操作?
(y/n)"<cin>>flag;
break;
}
default:
cout<<"无此选项请确定后再输入!
"<break;
}
}while(flag=='y'||flag=='Y');
}
3.2程序的输入和输出
创建二叉树的操作如图3.1所示
图3.1
非递归先,中,后序排列如图3.2所示
图3.2
计算二叉树结点总数,双孩子单孩子结点数,叶子结点数如图3.3所示
图3.3
判断二叉树高度如图3.4所示
图3.4
判断结点层次如图3.5所示
图3.5
3.3调试程序中遇到的问题及解决方案
问题:
首先要按照提示输入,在创建二叉树的时候,要注意二叉树的输入,要用“#”代替空,否则程序不能正确运行;每次执行新的任务的时候都要重新输入新的二叉树。
解决方案:
按照先序遍历输入二叉树,如果结点左孩子或右孩子为空则用“#”代替;求叶子结点数和求层次时,所先用的子函数中的参数初始赋值为零,再从头结点出发开始计数,直到所求结点。
第4章思考题解析
4.1思考题的选择
所选择的思考题:
编写一个算法,求一颗二叉树中每个结点平衡因子
4.2类C算法
intbtheight(BitTNode*BT)
{
intlh,rh,t;
if(BT==NULL)
return0;
else
{
lh=btheight(BT->lchild);/*计算左子数的高度*/
rh=btheight(BT->rchild);/*计算右子数的高度*/
if(lh<=rh)
t=rh;
else
t=lh;
BT->num=lh-rh;/*计算结点的平衡因子*/
returnt+1
}
}
4.3程序分析
结点的平衡因子等于其左子树结点层次减去其右子树结点层次,因此要想求得每个结点的平衡因子,就得在遍历每个结点的时候,算出其左,右子树的层次,程序中用到了递归调用子函数btheight(bitnode*bt),以求出每个节点的左右子树的高度,然后作差,结果保留在bt->num中,最后结果用return.返回
第5章总结
这是一门纯属于设计的科目,它需用把理论变为上机调试。
刚开始学的时候确实有很多地方我很不理解,每次上课时老师都会给我们出不同的设计题目,对于我们一个初学者来说,无疑是一个具大的挑战,撞了几次壁之后,我决定静下心来,仔细去写程序。
老师会给我们需要编程的内容一些讲解,顺着老师的思路,来完成自己的设计,我们可以开始运行自己的程序。
刚开始学的时候确实有很多地方我很不理解,每次上上机课时老师都会给我们出不同的设计题目,对于我们一个初学者来说,无疑是一个具大的挑战,撞了几次壁之后,我决定静下心来,仔细去写程序。
老师会给我们需要编程的内容一些讲解,顺着老师的思路,来完成自己的设计,我们可以开始运行自己的程序,可是好多处的错误让人看的可怕,还看不出到底是哪里出现了错误,但是程序还是得继续下去,我多次请教了老师和同学,逐渐能自己找出错误,并加以改正。
TC里检查错误都是用英文来显示出来的,经过了这次课程设计,现在已经可以了解很多错误在英文里的提示,这对我来说是一个突破性的进步,眼看着一个个错误通过自己的努力在我眼前消失,觉得很是开心。
此次的程序设计能够成功,是我和我的同学三个人共同努力作用的结果。
在这一段努力学习的过程中,我们的编程设计有了明显的提高。
其实现在想起来,收获还真是不少,虽然说以前非常不懂这门语言,在它上面花费了好多心血,觉得它很难,是需用花费了大量的时间编写出来的。
现在真正的明白了一些代码的应用,每个程序都有一些共同点,通用的结构,相似的格式。
只要努力去学习,就会灵活的去应用它。
本人签字:
参考文献
[1]徐孝凯编著.数据结构[M]第一版.北京:
机械工业出版社.1996年7月
[2]陈文博编著.数据结构[M]第二版.北京:
机械工业出版社.1996年8月
[3]许卓群编著.数据结构[M]第一版.北京:
高等教育出版社.1988年7月
[4]李廉治编著.数据结构教程[M]第一版.北京:
大连理工大学出版社.1989年1月
[5]晋良颍编著.数据结构简明教程[M]第三版.南京:
人民邮电出版社.2003年2月