二叉树的遍历讲解.docx
《二叉树的遍历讲解.docx》由会员分享,可在线阅读,更多相关《二叉树的遍历讲解.docx(24页珍藏版)》请在冰豆网上搜索。
![二叉树的遍历讲解.docx](https://file1.bdocx.com/fileroot1/2023-3/31/3093e9a1-5c99-40d4-ab6b-1c2daecf5ab5/3093e9a1-5c99-40d4-ab6b-1c2daecf5ab51.gif)
二叉树的遍历讲解
数据结构课程设计
设计题目:
基于文件实现二叉树的三种遍历
学生姓名:
汪碧霞
专业班级:
11算机科学与技术
(2)班
指导教师:
汪红霞
完成时间:
2012-12
信息工程学院计算机科学与技术系
课题名称
基于文件实现二叉树的三种遍历
院系
信息工程学院
年级专业
11软件技术
(2)班
学号
姓名
成绩
课题设计
目的与
设计意义
1、课题设计目的:
一.了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;
二.初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;
三.提高综合运用所学的理论知识和方法独立分析和解决问题的能力;
四.训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风
2、课题设计意义:
锻炼我们的编码能力,真正理解数据结构的编码思想,并且锻炼我们的动手能力和成员间的配合,提高程序编写能力。
指导教师:
汪红霞
2012年12月
安徽新华学院课程设计成绩评定表(专科)
1.设计目的
数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。
因此,主要有三个方面的内容:
数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。
通常,算法的设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。
数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。
在当今信息时代,信息技术己成为当代知识经济的核心技术。
我们时刻都在和数据打交道。
比如人们在外出工作时找最短路径,在银行查询存款、通过互联网查新闻、以及远程教育报名等,所有这些都在与数据发生关系。
实际上,现实世界中的实体经过抽象以后,就可以成为计算机上所处理的数据。
数据结构课程主要是研究非数值计算的程序设计问题中所出现的计算机操作对象以及它们之间的关系和操作的学科。
数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。
学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。
通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。
通过此次课程设计主要达到以下目的:
1、了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;
2、初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;
3、提高综合运用所学的理论知识和方法独立分析和解决问题的能力;
四训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风
2.需求分析
2.1课程设计的内容和要求(包括原始数据、技术要求、工作要求等)
二叉树的遍历:
对任意给定的二叉树(顶点数自定)建立它的二叉链表存贮结构,并利用栈的五种基本运算(置空栈、进栈、出栈、取栈顶元素、判栈空)实现二叉树的先序、中序、后序三种遍历,输出三种遍历的结果。
2.2选题的意义及背景
二叉树的链式存储结构是用指针建立二叉树中结点之间的关系。
二叉链存储结构的每个结点包含三个域,分别是数据域,左孩子指针域,右孩子指针域。
因此每个结点为
由二叉树的定义知可把其遍历设计成递归算法。
共有前序遍历、中序遍历、后序遍历。
可先用这三种遍历输出二叉树的结点。
采用递归算法设计,以前序遍历为例,它要求首先要访问根节点,然后前序遍历左子树和前序遍历右子树。
特点在于所有未被访问的节点中,最后访问结点的左子树的根结点将最先被访问,这与堆栈的特点相吻合。
因此可借助堆栈实现二叉树的递归遍历。
将输出结果与递归结果比较来检验正确性,因此程序结果可做成菜单方便这两种算法的结果查看。
3.概要设计
3.1设计思想
建立一个完全二叉树
用堆栈实现的前序遍历:
算法思想:
(1).初始化一个堆栈
(2).把根节点的指针入栈
(3).当堆栈非空时执行循环步骤a到步骤c
a.出栈取得一个结点指针,访问该结点.
b.若该结点的右子树非空,将该结点的右子树指针入栈
c.若该结点的左子树非空,将该结点的左子树指针入栈
用堆栈实现的中序遍历:
算法思想:
(1).初始化一个堆栈
(2).将根结点的所有左结点入栈
(3).当堆栈非空时执行循环步骤a到步骤d
a.出栈取得一个结点指针
b.若该结点的右子树非空并且未被访问,将该结点的右子树指针入栈
c.访问该结点
d.若该结点的左子树非空并且未被访问,将该结点的左子树指针入栈
用堆栈实现的后序遍历
算法思想:
(1).初始化一个堆栈
(2).将根结点的所有左结点入栈
(3)当堆栈非空时执行循环步骤a到步骤d
a.出栈取得一个结点指针
b.若该结点的右子树非空并且未被访问,将该结点的右子树指针入栈
c.若该结点的左子树非空并且未被访问,将该结点的左子树指针入栈
d.访问该结点
例如:
输入7节点的二叉树。
它的前序遍历为:
1245367
它的中序遍历为:
4251637
它的后序遍历为:
4526731
1
2
3
4567
3.2函数关系:
图3.1函数间的关系
4.详细设计
4.1二叉树算法源程序
#include
#defineSTACK_MAXLEN30
//usingnamespacestd;
typedefstructBTreeNode
{
intwhere;
structBTreeNode*rightChild;
structBTreeNode*leftChild;
}TYPE_B_TREE_NODE,*TYPE_pB_TREE_NODE;
//堆栈的结构
classTStack
{
public:
voidpush(TYPE_pB_TREE_NODEpNode);//入栈
TYPE_pB_TREE_NODEpop();//出栈
intempty()
{
if(top==base)
return1;
else
return0;
}
TStack()
{
top=base=stackArray;
for(inti=0;istackArray[i]=NULL;
//cout<<"堆栈初始化完毕!
"<}
private:
TYPE_pB_TREE_NODEstackArray[STACK_MAXLEN];
TYPE_pB_TREE_NODE*top;
TYPE_pB_TREE_NODE*base;//指向指针的指针
};
voidTStack:
:
push(TYPE_pB_TREE_NODEpNode)
{
*top=pNode;
top++;
}
TYPE_pB_TREE_NODETStack:
:
pop()
{
TYPE_pB_TREE_NODEreturnValue;
top--;
returnValue=(*top);
*top=NULL;
returnreturnValue;
}
//建立一个简单的完全二叉树
TYPE_pB_TREE_NODECreateBTree()
{
inti=0;
intNodeNum;
TYPE_pB_TREE_NODEpBTreeArray,pBTree;
cout<<"请输入完全二叉树的节点数:
"<cin>>NodeNum;
pBTreeArray=newTYPE_B_TREE_NODE[NodeNum];
for(i=1;i<=NodeNum/2-1;i++)
{
pBTreeArray[i-1].where=i;
pBTreeArray[i-1].leftChild=pBTreeArray+(2*i-1);
pBTreeArray[2*i-1].where=2*i;
pBTreeArray[i-1].rightChild=pBTreeArray+(2*i);
pBTreeArray[2*i].where=2*i+1;
}
if(2*i+1==NodeNum)
{
pBTreeArray[i-1].where=i;
pBTreeArray[i-1].leftChild=pBTreeArray+(2*i-1);
pBTreeArray[2*i-1].where=2*i;
pBTreeArray[i-1].rightChild=pBTreeArray+(2*i);
pBTreeArray[2*i].where=2*i+1;
}
else
{
pBTreeArray[i-1].where=i;
pBTreeArray[i-1].leftChild=pBTreeArray+(2*i-1);
pBTreeArray[2*i-1].where=2*i;
pBTreeArray[2*i].rightChild=NULL;
}
for(intj=i+1;j<=NodeNum;j++)
{
pBTreeArray[j-1].leftChild=NULL;
pBTreeArray[j-1].rightChild=NULL;
}
returnpBTree=pBTreeArray+0;
}
//
voidPrintBTree(TYPE_pB_TREE_NODEpBTreeRoot)
{
if(pBTreeRoot!
=NULL)
{
cout<where<PrintBTree(pBTreeRoot->leftChild);
PrintBTree(pBTreeRoot->rightChild);
}
}
//先序遍历
voidPreOrder(TYPE_pB_TREE_NODEpBTreeRoot)
{
cout<<"先序遍历"<TStackstack;
TYPE_pB_TREE_NODEpTemporary;
pTemporary=pBTreeRoot;
while(pTemporary!
=NULL)
{
cout<where<stack.push(pTemporary);
pTemporary=pTemporary->leftChild;
}
while(stack.empty()!
=1)
{
pTemporary=stack.pop();
if(pTemporary->rightChild==NULL)
{
continue;
}
else
{
pTemporary=pTemporary->rightChild;
while(pTemporary!
=NULL)
{
cout<where<stack.push(pTemporary);
pTemporary=pTemporary->leftChild;
}
}
}
}
//中序遍历
voidInOrder(TYPE_pB_TREE_NODEpBTreeRoot)
{
cout<<"中序遍历"<TStackstack;
TYPE_pB_TREE_NODEpTemporary;
pTemporary=pBTreeRoot;
while(pTemporary!
=NULL)
{
//cout<where<stack.push(pTemporary);
pTemporary=pTemporary->leftChild;
}
while(stack.empty()!
=1)
{
pTemporary=stack.pop();
cout<where<if(pTemporary->rightChild==NULL)
{
continue;
}
else
{
pTemporary=pTemporary->rightChild;
while(pTemporary!
=NULL)
{
//
stack.push(pTemporary);
pTemporary=pTemporary->leftChild;
}
}
}
}
//后序遍历
voidPostOrder(TYPE_pB_TREE_NODEpBTreeRoot)
{
cout<<"后序遍历"<TStackstack;
TYPE_pB_TREE_NODEpTemporary;
int*pFlag;
//intwithNoChild;
intflag[STACK_MAXLEN];
for(inti=0;iflag[i]=0;
pFlag=flag;
stack.push(pBTreeRoot);
while(stack.empty()!
=1)
{
pTemporary=stack.pop();
if(*pFlag==1)
{
cout<where<*pFlag=0;
pFlag--;
}
else
{
(*pFlag)++;
stack.push(pTemporary);
//withNoChild=0;
if(pTemporary->rightChild!
=NULL)
{
stack.push(pTemporary->rightChild);
pFlag++;
//withNoChild++;
}
if(pTemporary->leftChild!
=NULL)
{
stack.push(pTemporary->leftChild);
pFlag++;
//withNoChild++;
}
}
}
}
voidmain()
{
TYPE_pB_TREE_NODEpBTreeRoot;
pBTreeRoot=CreateBTree();
//PrintBTree(pBTreeRoot);
PreOrder(pBTreeRoot);
InOrder(pBTreeRoot);
PostOrder(pBTreeRoot);
}
4.2程序结果截图
输入节点数为7的二叉树:
输入节点为5的二叉树:
输入节点为3的二叉树:
5.程序测试结果及问题分析
通过与递归的遍历结果相比较之后,用堆栈实现的非递归遍历算法得出了正确的遍历结果,可以对二叉树进行遍历操作。
但是程序中树的结点已经建立好不能随意改动这确实是一个缺点因此可以进行改进,可以用递归的方法建立一棵二叉树,先建立左子树,在建立右子树这样用户输入的字符可以直接用来建树程序的灵活性会更强。
6.总结
通过一周的数据结构实训,进一步加深了对数据结构整体的理解,明白了链表的各种操作的实质,并且对老师课上讲的各种算法进行了实际的运用,更加掌握了各种算法的使用方法,例如链表的创建,查找,插入,二叉树的遍历等算法。
而且,通过这一次的实训,不仅加深了对数据结构知识的了解,更复习了以前学习过的C语言,重新复习了栈等经典算法,而且对于以前不懂得地方,例如主函数与子函数之间的实参,形参之间的传递,并且在二叉树的遍历部分复习了递归算法的使用。
这一周的实训,我深刻的领悟到,遇到困难,一定不要畏惧,自己多动脑思考思考,所联系自己以前学过的知识,便会有很大的进展,还有就是,往往一些错误都不是编写的逻辑错误,而是一些小错误点,例如忘记另外一部分的大括号,忘记分号等等,这提醒自己以后要细心,不要错在一些小问题上。
在这次课程设计中在,虽然不会成功的编写一个完整的程序,但是在看程序的过程中,不断的上网查资料以及翻阅相关书籍,通过不断的模索,测试,发现问题,解决问题和在老师的帮助下一步一步慢慢的正确运行程序决问题,终于完成了这次课程设计,虽然这次课程设计结束了但是总觉得自已懂得的知识很是不足,学无止境,以后还会更加的努力深入的学习。
7.参考文献
[1]严蔚敏,吴伟民.数据结构(C语言版),北京:
清华大学出版社,2009.
[2]顾泽元,刘文强,数据结构(C语言版),北京:
北京航空航天大学出版社,2011
[3]徐德民.《最新C语言程序设计》[M]电子工业出版社.1992年
[4]唐策善,黄刘生.《数据结构》[M]中国科学技术出版社.1992年
[5]仲萃豪,冯玉琳.《程序设计方法学》[M]北京科学技术出版社.1985年
[6]宁正元,王秀丽,《算法与数据结构》清华大学出版社,2006
[7]潭浩强,《数据结构教程上级实验指导》清华大学出版社,2008.
[8]朱站立,《数据结构-使用C语言》西安:
西安交通大学出版社,2004.
8.附录:
源程序
}