二叉树实验报告
- 格式:doc
- 大小:164.00 KB
- 文档页数:18
实验报告:二叉树第一篇:实验报告:二叉树实验报告二叉树一实验目的1、进一步掌握指针变量,动态变量的含义;2、掌握二叉树的结构特性以及各种存储结构的特点及适用范围。
3、掌握用指针类型描述、访问和处理二叉树的运算。
4、熟悉各种存储结构的特征以及如何应用树结构解决具体问题。
二实验原理树形结构是一种应用十分广泛和重要的非线性数据结构,是一种以分支关系定义的层次结构。
在这种结构中,每个数据元素至多只有一个前驱,但可以有多个后继;数据元素之间的关系是一对多的层次关系。
树形结构主要用于描述客观世界中具有层次结构的数据关系,它在客观世界中大量存在。
遍历二叉树的实质是将非线性结构转为线性结构。
三使用仪器,材料计算机 2 Wndows xp 3 VC6.0四实验步骤【问题描述】建立一个二叉树,请分别按前序,中序和后序遍历该二叉树。
【基本要求】从键盘接受输入(按前序顺序),以二叉链表作为存储结构,建立二叉树(以前序来建立),并采用递归算法对其进行前序,中序和后序遍历,将结果输出。
【实现提示】按前序次序输入二叉树中结点的值(一个整数),0表示空树,叶子结点的特征是其左右孩子指针为空。
五实验过程原始记录基本数据结构描述; 2 函数间的调用关系;用类C语言描述各个子函数的算法;附录:源程序。
六试验结果分析将实验结果分析、实验中遇到的问题和解决问题的方法以及关于本实验项目的心得体会,写在实验报告上。
第二篇:数据结构-二叉树的遍历实验报告实验报告课程名:数据结构(C语言版)实验名:二叉树的遍历姓名:班级:学号:时间:2014.11.03一实验目的与要求1.掌握二叉树的存储方法2.掌握二叉树的三种遍历方法3.实现二叉树的三种遍历方法中的一种二实验内容• 接受用户输入一株二叉树• 输出这株二叉树的前根, 中根, 后根遍历中任意一种的顺序三实验结果与分析//*********************************************************** //头文件#include #include //*********************************************************** //宏定义#define OK 1 #define ERROR 0 #define OVERFLOW 0//*********************************************************** typedef struct BiTNode { //二叉树二叉链表存储结构char data;struct BiTNode *lChild,*rChild;}BiTNode,*BiTree;//******************************** *************************** int CreateBiTree(BiTree &T){ //按先序次序输入二叉中树结点的值,空格表示空树//构造二叉链表表示的二叉树T char ch;fflush(stdin);scanf(“%c”,&ch);if(ch==' ')T=NULL;else{ if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))return(OVERFLOW);T->data=ch;Creat eBiTree(T->lChild);CreateBiTree(T->rChild);} return(OK);} //********************************************************* void PreOrderTraverse(BiTree T){ //采用二叉链表存储结构,先序遍历二叉树的递归算法if(T){ printf(“%c”,T->data);PreOrderTraverse(T->lChild);PreOrd erTraverse(T->rChild);} } /***********************************************************/ void InOrderTraverse(BiTree T){ //采用二叉链表存储结构,中序遍历二叉树的递归算法if(T){ InOrderTraverse(T->lChild);printf(“%c”,T->data);InOrderT raverse(T->rChild);} }//*********************************************************** void PostOrderTraverse(BiTree T){ //采用二叉链表存储结构,后序遍历二叉树的递归算法if(T){ PostOrderTraverse(T->lChild);PostOrderTraverse(T->rChild) ;printf(“%c”,T->data);} }//*********************************************************** void main(){ //主函数分别实现建立并输出先、中、后序遍历二叉树printf(“please input your tree follow the PreOrder:n”);BiTNode *Tree;CreateBiTree(Tree);printf(“n先序遍历二叉树:”);PreOrderTraverse(Tree);printf(“n中序遍历二叉树:”);InOrderTraverse(Tree);printf(“n后序遍历二叉树:”);PostOrderTraverse(Tree);}图1:二叉树的遍历运行结果第三篇:数据结构二叉树操作验证实验报告班级:计算机11-2 学号:40 姓名:朱报龙成绩:_________实验七二叉树操作验证一、实验目的⑴ 掌握二叉树的逻辑结构;⑵ 掌握二叉树的二叉链表存储结构;⑶ 掌握基于二叉链表存储的二叉树的遍历操作的实现。
二叉排序树的实验报告二叉排序树的实验报告引言:二叉排序树(Binary Search Tree,简称BST)是一种常用的数据结构,它将数据按照一定的规则组织起来,便于快速的查找、插入和删除操作。
本次实验旨在深入了解二叉排序树的原理和实现,并通过实验验证其性能和效果。
一、实验背景二叉排序树是一种二叉树,其中每个节点的值大于其左子树的所有节点的值,小于其右子树的所有节点的值。
这种特性使得在二叉排序树中进行查找操作时,可以通过比较节点的值来确定查找的方向,从而提高查找效率。
二、实验目的1. 理解二叉排序树的基本原理和性质;2. 掌握二叉排序树的构建、插入和删除操作;3. 验证二叉排序树在查找、插入和删除等操作中的性能和效果。
三、实验过程1. 构建二叉排序树首先,我们需要构建一个空的二叉排序树。
在构建过程中,我们可以选择一个节点作为根节点,并将其他节点插入到树中。
插入节点时,根据节点的值与当前节点的值进行比较,如果小于当前节点的值,则将其插入到当前节点的左子树中;如果大于当前节点的值,则将其插入到当前节点的右子树中。
重复这个过程,直到所有节点都被插入到树中。
2. 插入节点在已有的二叉排序树中插入新的节点时,我们需要遵循一定的规则。
首先,从根节点开始,将新节点的值与当前节点的值进行比较。
如果小于当前节点的值,则将其插入到当前节点的左子树中;如果大于当前节点的值,则将其插入到当前节点的右子树中。
如果新节点的值与当前节点的值相等,则不进行插入操作。
3. 删除节点在二叉排序树中删除节点时,我们需要考虑不同的情况。
如果要删除的节点是叶子节点,即没有左右子树,我们可以直接删除该节点。
如果要删除的节点只有一个子树,我们可以将子树连接到要删除节点的父节点上。
如果要删除的节点有两个子树,我们可以选择将其右子树中的最小节点或左子树中的最大节点替代该节点,并删除相应的替代节点。
四、实验结果通过对二叉排序树的构建、插入和删除操作的实验,我们得到了以下结果:1. 二叉排序树可以高效地进行查找操作。
二叉树的建立和遍历的实验报告篇一:二叉树的建立及遍历实验报告实验三:二叉树的建立及遍历【实验目的】(1)掌握利用先序序列建立二叉树的二叉链表的过程。
(2)掌握二叉树的先序、中序和后序遍历算法。
【实验内容】1. 编写程序,实现二叉树的建立,并实现先序、中序和后序遍历。
如:输入先序序列abc###de###,则建立如下图所示的二叉树。
并显示其先序序列为:abcde中序序列为:cbaed后序序列为:cbeda【实验步骤】1.打开VC++。
2.建立工程:点File->New,选Project标签,在列表中选Win32 Console Application,再在右边的框里为工程起好名字,选好路径,点OK->finish。
至此工程建立完毕。
3.创建源文件或头文件:点File->New,选File标签,在列表里选C++ Source File。
给文件起好名字,选好路径,点OK。
至此一个源文件就被添加到了你刚创建的工程之中。
4.写好代码5.编译->链接->调试#include#include#define OK 1#define OVERFLOW -2typedef int Status;typedef char TElemType;typedef struct BiTNode{TElemType data;struct BiTNode *lchild, *rchild;}BiTNode,*BiTree;Status CreateBiTree(BiTree &T){TElemType ch;scanf("%c",&ch);if (ch=='#')T= NULL;else{if (!(T = (BiTNode *)malloc(sizeof(BiTNode))))return OVERFLOW;T->data = ch; CreateBiTree(T->lchild); CreateBiTree(T->rchild); }return OK;} // CreateBiTreevoid PreOrder(BiTree T) {if(T){printf("%c",T->data); PreOrder(T->lchild); PreOrder(T->rchild);}}void InOrder(BiTree T) {if(T){InOrder(T->lchild);printf("%c",T->data);InOrder(T->rchild);}}void PostOrder(BiTree T){if(T){PostOrder(T->lchild); PostOrder(T->rchild);printf("%c",T->data);}}void main(){BiTree T;CreateBiTree(T);printf("\n先序遍历序列:"); PreOrder(T);printf("\n中序遍历序列:"); InOrder(T);printf("\n后序遍历序列:"); PostOrder(T);}【实验心得】这次实验主要是通过先序序列建立二叉树,和二叉树的先序、中序、后续遍历算法。
二叉树的遍历算法实验报告二叉树的遍历算法实验报告引言:二叉树是计算机科学中常用的数据结构之一,它是由节点组成的层次结构,每个节点最多有两个子节点。
在实际应用中,对二叉树进行遍历是一项重要的操作,可以帮助我们理解树的结构和节点之间的关系。
本文将介绍二叉树的三种遍历算法:前序遍历、中序遍历和后序遍历,并通过实验验证其正确性和效率。
一、前序遍历前序遍历是指先访问根节点,然后按照先左后右的顺序遍历左右子树。
具体的实现可以通过递归或者使用栈来实现。
我们以递归方式实现前序遍历算法,并进行实验验证。
实验步骤:1. 创建一个二叉树,并手动构造一些节点和它们之间的关系。
2. 实现前序遍历算法的递归函数,函数的输入为根节点。
3. 在递归函数中,首先访问当前节点,然后递归调用函数遍历左子树,最后递归调用函数遍历右子树。
4. 调用前序遍历函数,输出遍历结果。
实验结果:经过实验,我们得到了正确的前序遍历结果。
这证明了前序遍历算法的正确性。
二、中序遍历中序遍历是指按照先左后根再右的顺序遍历二叉树。
同样,我们可以使用递归或者栈来实现中序遍历算法。
在本实验中,我们选择使用递归方式来实现。
实验步骤:1. 继续使用前面创建的二叉树。
2. 实现中序遍历算法的递归函数,函数的输入为根节点。
3. 在递归函数中,首先递归调用函数遍历左子树,然后访问当前节点,最后递归调用函数遍历右子树。
4. 调用中序遍历函数,输出遍历结果。
实验结果:通过实验,我们得到了正确的中序遍历结果。
这证明了中序遍历算法的正确性。
三、后序遍历后序遍历是指按照先左后右再根的顺序遍历二叉树。
同样,我们可以使用递归或者栈来实现后序遍历算法。
在本实验中,我们选择使用递归方式来实现。
实验步骤:1. 继续使用前面创建的二叉树。
2. 实现后序遍历算法的递归函数,函数的输入为根节点。
3. 在递归函数中,首先递归调用函数遍历左子树,然后递归调用函数遍历右子树,最后访问当前节点。
4. 调用后序遍历函数,输出遍历结果。
二叉树的各种基本运算的实现实验报告
一、实验目的
实验目的为了深入学习二叉树的各种基本运算,通过操作实现二叉树的建立、存储、查找、删除、遍历等各种基本运算操作。
二、实验内容
1、构造一个二叉树。
我们首先用一定的节点来构建一棵二叉树,包括节点的左子节点和右子节点。
2、实现查找二叉树中的节点。
在查找二叉树中的节点时,我们根据二叉树的特点,从根节点开始查找,根据要查找的节点的值与根节点的值的大小的关系,来决定接下来查找的方向,直到找到要查找的节点为止。
3、实现删除二叉树中的节点。
在删除二叉树节点时,我们要做的是找到要删除节点的父节点,然后让父节点的链接指向要删除节点的子节点,有可能要删除节点有一个子节点,有可能有两个极点,有可能没有子节点,我们要根据每种情况进行处理,来保持二叉树的结构不变。
4、对二叉树进行遍历操作。
二叉树的遍历有多种方法,本实验使用的是先序遍历。
首先从根节点出发,根据先序遍历的顺序,先访问左子树,然后再访问右子树,最后访问根节点。
三、实验步骤
1、构建二叉树:
我们用一个数组代表要构建的二叉树,第一项为根节点,第二项和第三项是根节点的子节点。
二叉树的遍历实验报告实验报告:二叉树的遍历(先序遍历、中序遍历、后序遍历)一、引言二叉树是一种非常常见的数据结构,在计算机领域有着广泛的应用。
对二叉树进行遍历操作是其中最基本的操作之一、本实验旨在通过对二叉树的先序遍历、中序遍历和后序遍历的实践,加深对二叉树遍历算法的理解和掌握。
二、目的1.掌握二叉树先序遍历的算法原理和实现方法;2.掌握二叉树中序遍历的算法原理和实现方法;3.掌握二叉树后序遍历的算法原理和实现方法;4.使用递归和非递归两种方式实现以上三种遍历算法;5.进行正确性验证和性能评估。
三、方法1.算法原理:1.1先序遍历:先访问根节点,然后递归遍历左子树,再递归遍历右子树;1.2中序遍历:先递归遍历左子树,然后访问根节点,最后递归遍历右子树;1.3后序遍历:先递归遍历左子树,再递归遍历右子树,最后访问根节点。
2.实现方法:2.1递归实现:采用函数递归调用的方式,实现对二叉树的遍历;2.2非递归实现:采用栈的数据结构,模拟递归的过程,实现对二叉树的遍历。
四、实验步骤1.数据结构设计:1.1定义二叉树的节点结构,包括节点值和两个指针(分别指向左子节点和右子节点);1.2定义一个栈结构,用于非递归实现时的辅助存储。
2.先序遍历:2.1递归实现:按照先序遍历的原理,通过递归调用遍历左子树和右子树,再输出根节点;2.2非递归实现:通过栈结构模拟递归的过程,先将根节点入栈,然后循环将栈顶节点弹出并输出,再将其右子节点入栈,最后将左子节点入栈,直到栈为空。
3.中序遍历:3.1递归实现:按照中序遍历的原理,通过递归调用先遍历左子树,再输出根节点,最后遍历右子树;3.2非递归实现:先将根节点入栈,然后循环将左子节点入栈,直到左子节点为空,然后弹出栈顶节点并输出,再将其右子节点入栈,重复以上过程直到栈为空。
4.后序遍历:4.1递归实现:按照后序遍历的原理,通过递归调用先遍历左子树,再遍历右子树,最后输出根节点;4.2非递归实现:通过栈结构模拟递归的过程,先将根节点入栈,然后重复以下步骤直到栈为空。
实习报告一、需求分析1、问题描述利用平衡二叉树实现一个动态查找表。
(1)实现动态查找表的三种基本功能:查找、插入和删除。
(2)初始时,平衡二叉树为空树,操作界面给出查找、插入和删除三种操作供选择。
每种操作均要提示输入关键字。
在查找时,如果查找的关键字不存在,则把其插入到平衡二叉树中。
每次插入或删除一个结点后,应更新平衡二叉树的显示。
(3)每次操作的关键字都要从文件中读取,并且关键字的集合限定为短整型数字{1,2,3······},关键字出现的顺序没有限制,允许出现重复的关键字,并对其进行相应的提示。
(4)平衡二叉树的显示采用图形界面画出图形。
2、系统功能打开数据文件,用文件中的关键字来演示平衡二叉树操作的过程。
3、程序中执行的命令包括:(1)(L)oad from data file //在平衡的二叉树中插入关键字;(2)(A)ppend new record //在平衡的二叉树中查找关键字;(3)(U)pate special record //显示调整过的平衡二叉树;(4)(D)elete special record //删除平衡二叉树中的关键字;(5)(Q)uit //结束。
4、测试数据:平衡二叉树为:图 1 插入关键字10之前的平衡二叉树插入关键字:10;调整后:图 2 插入关键字10之后的平衡二叉树删除关键字:14;调整后:图 3 删除关键字14后的平衡二叉树查找关键字:11;输出:The data is here!图 3 查找关键字11后的平衡二叉树二、概要设计本次实验目的是为了实现动态查找表的三种基本功能:查找、插入和删除。
动态查找表可有不同的表示方法,在此次实验中主要是以平衡二叉树的结构来表示实现的,所以需要两个抽象数据类型:动态查找表和二叉树。
1、动态查找表的抽象数据类型定义为:ADT DynamicSearchTable{数据对象D :D是具有相同特性的数据元素的集合。
二叉树实验报告二叉树实验报告引言:二叉树是一种常见的数据结构,它由节点和边组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。
在本次实验中,我们将探索二叉树的基本概念、特性以及应用。
一、二叉树的定义与性质1.1 二叉树的定义二叉树是一种递归定义的数据结构,它可以为空,或者由一个根节点和两个二叉树组成,分别称为左子树和右子树。
1.2 二叉树的性质(1)每个节点最多有两个子节点,分别称为左子节点和右子节点。
(2)左子树和右子树也是二叉树。
(3)二叉树的子树之间没有关联性,它们是相互独立的。
二、二叉树的遍历方式2.1 前序遍历前序遍历是指先访问根节点,然后按照先左后右的顺序遍历左子树和右子树。
2.2 中序遍历中序遍历是指先遍历左子树,然后访问根节点,最后遍历右子树。
2.3 后序遍历后序遍历是指先遍历左子树,然后遍历右子树,最后访问根节点。
2.4 层次遍历层次遍历是指按照从上到下、从左到右的顺序遍历二叉树的每个节点。
三、二叉树的应用3.1 二叉搜索树二叉搜索树是一种特殊的二叉树,它的每个节点的值大于其左子树的所有节点的值,小于其右子树的所有节点的值。
这种特性使得二叉搜索树可以高效地进行查找、插入和删除操作。
3.2 哈夫曼树哈夫曼树是一种带权路径长度最短的二叉树,它常用于数据压缩中。
哈夫曼树的构建过程是通过贪心算法,将权值较小的节点放在离根节点较远的位置,从而实现最优编码。
3.3 表达式树表达式树是一种用于表示数学表达式的二叉树,它的叶节点是操作数,而非叶节点是操作符。
通过对表达式树的遍历,可以实现对表达式的求值。
结论:通过本次实验,我们对二叉树的定义、性质、遍历方式以及应用有了更深入的了解。
二叉树作为一种重要的数据结构,在计算机科学和算法设计中发挥着重要的作用。
在今后的学习和工作中,我们应该进一步探索二叉树的高级应用,并灵活运用于实际问题的解决中。
二叉树实验报告1. 引言二叉树是一种常用的数据结构,广泛应用于计算机科学和信息技术领域。
本实验旨在通过对二叉树的理解和实现,加深对数据结构与算法的认识和应用能力。
本报告将介绍二叉树的定义、基本操作以及实验过程中的设计和实现。
2. 二叉树的定义二叉树是一个有序树,其每个节点最多有两个子节点。
树的左子节点和右子节点被称为二叉树的左子树和右子树。
3. 二叉树的基本操作3.1 二叉树的创建在实验中,我们通过定义一个二叉树的节点结构来创建一个二叉树。
节点结构包含一个数据域和左右指针,用于指向左右子节点。
创建二叉树的过程可以通过递归或者迭代的方式来完成。
3.2 二叉树的插入和删除二叉树的插入操作是将新节点插入到树中的合适位置。
插入时需要考虑保持二叉树的有序性。
删除操作是将指定节点从树中删除,并保持二叉树的有序性。
在实验中,我们可以使用递归或者循环的方式实现这些操作。
3.3 二叉树的遍历二叉树的遍历是指按照某种次序访问二叉树的所有节点。
常见的遍历方式包括前序遍历、中序遍历和后序遍历。
前序遍历先访问根节点,然后按照左孩子-右孩子的顺序递归遍历左右子树。
中序遍历按照左孩子-根节点-右孩子的顺序递归遍历左右子树。
后序遍历按照左孩子-右孩子-根节点的顺序递归遍历左右子树。
3.4 二叉树的查找查找操作是指在二叉树中查找指定的值。
可以通过递归或者循环的方式实现二叉树的查找操作。
基本思路是从根节点开始,通过比较节点的值和目标值的大小关系,逐步向左子树或者右子树进行查找,直到找到目标节点或者遍历到叶子节点。
4. 实验设计和实现在本实验中,我们设计并实现了一个基于Python语言的二叉树类。
具体实现包括二叉树的创建、插入、删除、遍历和查找操作。
在实验过程中,我们运用了递归和迭代的方法实现了这些操作,并进行了测试和验证。
4.1 二叉树类的设计我们将二叉树的节点设计为一个类,其中包括数据域和左右子节点的指针。
另外,我们设计了一个二叉树类,包含了二叉树的基本操作方法。
实验5:树(二叉树)(采用二叉链表存储)一、实验项目名称二叉树及其应用二、实验目的熟悉二叉树的存储结构的特性以及二叉树的基本操作。
三、实验基本原理之前我们都是学习的线性结构,这次我们就开始学习非线性结构——树。
线性结构中结点间具有唯一前驱、唯一后继关系,而非线性结构中结点的前驱、后继的关系并不具有唯一性。
在树结构中,节点间关系是前驱唯一而后继不唯一,即结点之间是一对多的关系。
直观地看,树结构是具有分支关系的结构(其分叉、分层的特征类似于自然界中的树)。
四、主要仪器设备及耗材Window 11、Dev-C++5.11五、实验步骤1.导入库和预定义2.创建二叉树3.前序遍历4.中序遍历5.后序遍历6.总结点数7.叶子节点数8.树的深度9.树根到叶子的最长路径10.交换所有节点的左右子女11.顺序存储12.显示顺序存储13.测试函数和主函数对二叉树的每一个操作写测试函数,然后在主函数用while+switch-case的方式实现一个带菜单的简易测试程序,代码见“实验完整代码”。
实验完整代码:#include <bits/stdc++.h>using namespace std;#define MAX_TREE_SIZE 100typedef char ElemType;ElemType SqBiTree[MAX_TREE_SIZE];struct BiTNode{ElemType data;BiTNode *l,*r;}*T;void createBiTree(BiTNode *&T){ElemType e;e = getchar();if(e == '\n')return;else if(e == ' ')T = NULL;else{if(!(T = (BiTNode *)malloc(sizeof (BiTNode)))){cout << "内存分配错误!" << endl;exit(0);}T->data = e;createBiTree(T->l);createBiTree(T->r);}}void createBiTree2(BiTNode *T,int u) {if(T){SqBiTree[u] = T->data;createBiTree2(T->l,2 * u + 1);createBiTree2(T->r,2 * u + 2); }}void outputBiTree2(int n){int cnt = 0;for(int i = 0;cnt <= n;i++){cout << SqBiTree[i];if(SqBiTree[i] != ' ')cnt ++;}cout << endl;}void preOrderTraverse(BiTNode *T) {if(T){cout << T->data;preOrderTraverse(T->l);preOrderTraverse(T->r);}}void inOrderTraverse(BiTNode *T) {if(T){inOrderTraverse(T->l);cout << T->data;inOrderTraverse(T->r);}}void beOrderTraverse(BiTNode *T){if(T){beOrderTraverse(T->l);beOrderTraverse(T->r);cout << T->data;}}int sumOfVer(BiTNode *T){if(!T)return 0;return sumOfVer(T->l) + sumOfVer(T->r) + 1;}int sumOfLeaf(BiTNode *T){if(!T)return 0;if(T->l == NULL && T->r == NULL)return 1;return sumOfLeaf(T->l) + sumOfLeaf(T->r);}int depth(BiTNode *T){if(!T)return 0;return max(depth(T->l),depth(T->r)) + 1;}bool LongestPath(int dist,int dist2,vector<ElemType> &ne,BiTNode *T) {if(!T)return false;if(dist2 == dist)return true;if(LongestPath(dist,dist2 + 1,ne,T->l)){ne.push_back(T->l->data);return true;}else if(LongestPath(dist,dist2 + 1,ne,T->r)){ne.push_back(T->r->data);return true;}return false;}void swapVer(BiTNode *&T){if(T){swapVer(T->l);swapVer(T->r);BiTNode *tmp = T->l;T->l = T->r;T->r = tmp;}}//以下是测试程序void test1(){getchar();cout << "请以先序次序输入二叉树结点的值,空结点用空格表示:" << endl; createBiTree(T);cout << "二叉树创建成功!" << endl;}void test2(){cout << "二叉树的前序遍历为:" << endl;preOrderTraverse(T);cout << endl;}void test3(){cout << "二叉树的中序遍历为:" << endl;inOrderTraverse(T);cout << endl;}void test4(){cout << "二叉树的后序遍历为:" << endl;beOrderTraverse(T);cout << endl;}void test5(){cout << "二叉树的总结点数为:" << sumOfVer(T) << endl;}void test6(){cout << "二叉树的叶子结点数为:" << sumOfLeaf(T) << endl; }void test7(){cout << "二叉树的深度为:" << depth(T) << endl;}void test8(){int dist = depth(T);vector<ElemType> ne;cout << "树根到叶子的最长路径:" << endl;LongestPath(dist,1,ne,T);ne.push_back(T->data);reverse(ne.begin(),ne.end());cout << ne[0];for(int i = 1;i < ne.size();i++)cout << "->" << ne[i];cout << endl;}void test9(){swapVer(T);cout << "操作成功!" << endl;}void test10(){memset(SqBiTree,' ',sizeof SqBiTree);createBiTree2(T,0);cout << "操作成功!" << endl;}void test11(){int n = sumOfVer(T);outputBiTree2(n);}int main(){int op = 0;while(op != 12){cout << "-----------------menu--------------------" << endl;cout << "--------------1:创建二叉树--------------" << endl;cout << "--------------2:前序遍历----------------" << endl;cout << "--------------3:中序遍历----------------" << endl;cout << "--------------4:后序遍历----------------" << endl;cout << "--------------5:总结点数----------------" << endl;cout << "--------------6:叶子节点数--------------" << endl;cout << "--------------7:树的深度----------------" << endl;cout << "--------------8:树根到叶子的最长路径----" << endl;cout << "--------------9:交换所有节点左右子女----" << endl;cout << "--------------10:顺序存储---------------" << endl;cout << "--------------11:显示顺序存储-----------" << endl;cout << "--------------12:退出测试程序-----------" << endl;cout << "请输入指令编号:" << endl;if(!(cin >> op)){cin.clear();cin.ignore(INT_MAX,'\n');cout << "请输入整数!" << endl;continue;}switch(op){case 1:test1();break;case 2:test2();break;case 3:test3();break;case 4:test4();break;case 5:test5();break;case 6:test6();break;case 7:test7();break;case 8:test8();break;case 9:test9();break;case 10:test10();break;case 11:test11();break;case 12:cout << "测试结束!" << endl;break;default:cout << "请输入正确的指令编号!" << endl;}}return 0;}六、实验数据及处理结果测试用例:1.创建二叉树(二叉链表形式)2.前序遍历3.中序遍历4.后序遍历5.总结点数6.叶子结点数7.树的深度8.树根到叶子的最长路径9.交换所有左右子女10.顺序存储七、思考讨论题或体会或对改进实验的建议通过这次实验,我掌握了二叉树的顺序存储和链式存储,体会了二叉树的存储结构的特性,掌握了二叉树的树上相关操作。
题目:编程实现二叉查找树的建立、中序遍历、元素查找等功能,要求解释实现过程及演示实际例子的运行结果。
算法描述:首先创建二叉树结点类,其主要包括:二叉树结点数据域,指向左、右子树的指针,构造函数,设置当前结点左、右子树、数据域以及判断当前结点是否为叶子结点等。
然后进行二叉树类定义,其私有部分为定义二叉树根结点指针,公有部分主要包括:构造函数、析构函数、判断二叉树是否为空树、先,中,后序遍历的递归与非递归、二叉树删除、层序遍历以及二叉树搜索等。
接下来将对一些重要函数算法进行描述:1、isLeaf函数:若该结点的左子树和右子树都为空,则为叶子结点。
2、isEmpty函数:根结点为空则为空树。
3、Parent函数:首先判断给定结点是否有双亲,根结点和空结点一定无双亲,初始化一个临时变量,用于跟进查找双亲结点,查找到后其保存的便是双亲结点。
先递归在左子树中查找,如果找到,便结束递归且返回双亲结点指针;如果没有找到,再递归在右子树中查找。
如果都没有找到,说明给定结点的双亲结点不在该二叉树中。
4、LeftSibling(RightSibling)函数:首先找到当前结点的双亲,然后判断双亲结点左右子树是否为空,其中必然有一个不为空,返回另一个子树指针即可。
5、DeleteBinaryTree函数:首先判断是否为空树,若为空,则返回,然后递归删除左子树,递归删除右子树,最后删除根结点。
6、PreOrder函数:首先判断是否为空树,若为空,则返回,然后访问根结点,递归遍历左子树,递归遍历右子树,结束。
7、PreOrderWithoutRecusion函数:使用栈来模拟递归过程,首先申请栈,用于保存结点指针序列,申请指针pointer保存当前根指针,然后判断栈是否为空,若栈为空且pointer为空,跳出函数,否则若pointer不为空,访问pointer所指结点,pointer入栈,pointer指向其左子树;若pointer为空,弹出栈顶元素赋给pointer,pointer指向其右子树,结束。
8、CreateTree函数:采用先序遍历序列构造二叉树,设‘0’为空结点,输入非‘0’数,生成新结点,递归创建左子树和右子树。
9、Search函数:采用先序遍历查找给定元素是否在二叉树中,首先判断树是否是空树,若是空树,则返回空指针。
然后初始化临时指针temp,查找成功后temp即为所给元素所在结点的指针。
如果当前结点为空,则返回;否则判断当前结点是否为目标结点,如果是,记住结点位置,返回;否则,递归地在左子树中查找,如果找到,记住结点位置,返回;否则,递归地在右子树中查找。
判断temp是否为空,若为空,则未查找到给定元素。
10、LevelOrder函数:利用队列记录二叉树每一层,首先申请队列,申请指针pointer 保存根结点,然后判断pointer是否为空,若不为空,则pointer入队。
如果队列为空,跳出函数。
队列首元素出队,赋给pointer,访问pointer所指结点,如果pointer所指结点的左子树不为空,则左子树根结点指针入队;如果pointer所指结点的右子树不为空,则右子树根结点指针入队,结束。
先序遍历,后序遍历思想与中序遍历一致,这里不再一一分析。
最后创建一颗二叉树,用以检验各函数的功能。
源程序:#include<iostream>#include<stack>#include<queue>#include <cstdlib>using namespace std;template < class T >class BinaryTree;template < class T >class BinaryTreeNode{friend class BinaryTree< T >;//friend class BinarySearchTree< T >;private:T data; //二叉树结点数据域BinaryTreeNode< T > * left; //二叉树结点指向左子树的指针BinaryTreeNode< T > * right; //二叉树结点指向右子树的指针public:BinaryTreeNode(){}; //默认构造函数BinaryTreeNode(const T& ele) :left(NULL), right(NULL) {data = ele;};//给定数据的构造函数BinaryTreeNode(const T& ele,BinaryTreeNode< T > * l,BinaryTreeNode< T > * r);//给定数据的左右指针的构造函数~BinaryTreeNode(){}; //析构函数T value() const{return data;}; //返回当前结点的数据BinaryTreeNode< T >&operator=(const BinaryTreeNode< T >&Node){this=Node;};//重载赋值操作符BinaryTreeNode< T > * leftchild() const{return left;};//返回当前结点指向左子树的指针BinaryTreeNode< T > * rightchild() const{return right;};//返回当前结点指向右子树的指针void setLeftchild(BinaryTreeNode< T > * l){left = l;};//设置当前结点的左子树void setRightchild(BinaryTreeNode< T > * r){right = r;};//设置当前结点的右子树void setValue(const T& val){data = val;};//设置当前结点的数据域bool isLeaf() const; //判定当前结点是否为叶子结点,若是则返回true };template < class T >BinaryTreeNode< T >::BinaryTreeNode(const T& ele,BinaryTreeNode< T > * l,BinaryTreeNode< T > * r) //给定数据的左右指针的构造函数{data = ele;left = l;right = r;}template < class T >bool BinaryTreeNode< T >::isLeaf() const //判定当前结点是否为叶子结点,若是则返回true{if(data->left == NULL && data->right == NULL) //若左子树和右子树都为空,则返回truereturn true;elsereturn false;}template < class T >class BinaryTree{protected:BinaryTreeNode< T > * ROOT; //二叉树根结点指针public:BinaryTree(){ROOT=NULL;}; //构造函数BinaryTree(BinaryTreeNode< T > * r){ROOT = r;}~BinaryTree(){DeleteBinaryTree(ROOT);}; //析构函数bool isEmpty() const; //判断二叉树是否为空树void visit(const T& data){cout << data <<" ";} //访问当前结点BinaryTreeNode< T > * & Root(){return ROOT;}; //返回二叉树的根结点BinaryTreeNode< T > * Parent(BinaryTreeNode< T > * current);//返回当前结点的双亲结点void Parent_PreOrder(BinaryTreeNode< T > *curroot,BinaryTreeNode< T > *r,BinaryTreeNode< T > *&t); //运用先序遍历的思想查找双亲BinaryTreeNode< T > * LeftSibling(BinaryTreeNode< T > * current);//返回当前结点的左兄弟BinaryTreeNode< T > * RightSibling(BinaryTreeNode< T > * current);//返回当前结点的右兄弟void CreateTree(BinaryTreeNode< T > * &r); //根据先序遍历序列构造二叉树void DeleteBinaryTree(BinaryTreeNode< T > * root); //删除二叉树或其子树void PreOrder(BinaryTreeNode< T > * root); //先序遍历二叉树或其子树void InOrder(BinaryTreeNode< T > * root); //中序遍历二叉树或其子树void PostOrder(BinaryTreeNode< T > * root); //后序遍历二叉树或其子树void PreOrderWithoutRecusion(BinaryTreeNode< T > * root);//非递归先序遍历二叉树或其子树void InOrderWithoutRecusion(BinaryTreeNode< T > * root);//非递归中序遍历二叉树或其子树void PostOrderWithoutRecusion(BinaryTreeNode< T > * root);//非递归后序遍历二叉树或其子树void LevelOrder(BinaryTreeNode< T > * root); //按层序遍历二叉树或其子树BinaryTreeNode<T> * Search( T &t, BinaryTreeNode<T> *r ); //二叉树搜索void Search_PreOrder( T &t, BinaryTreeNode<T> *r, BinaryTreeNode<T> *&temp );//运用先序遍历的思想查找给定数据所在结点};template < class T >bool BinaryTree< T >::isEmpty() const //判断二叉树是否为空树{if(ROOT == NULL) //若根结点为空,则返回true return true;elsereturn false;}template <class T>BinaryTreeNode<T> * BinaryTree<T>::Parent( BinaryTreeNode<T> *current )//返回当前结点的双亲结点{if( !current || !ROOT || current == ROOT )//若当前结点不存在或根结点为空或当前结点为根结点,则输出error且跳出函数{cout << "Error\n";exit(0);}BinaryTreeNode<T> *temp = NULL;//初始化临时指针,temp用于保存最后查找到的双亲结点的地址Parent_PreOrder( ROOT, current, temp ); //查找双亲的子程序if(!temp) //结点不在树中,则双亲不存在{cout << "Your node doesn't belong to this tree!\n";exit(0);}return temp;}template <class T>void BinaryTree<T>::Parent_PreOrder( BinaryTreeNode<T> *curroot,BinaryTreeNode<T> *r, BinaryTreeNode<T> *&t ) //运用递归实现先序遍历,在遍历过程中判断是否找到双亲节点{if( !curroot || curroot->isLeaf() ) return; //当前结点为空或叶子结点if( r == curroot->left || r == curroot->right ) //判断双亲结点的条件{t = curroot; //t是对temp的引用,在此修改temp的值return;}else{Parent_PreOrder( curroot->left, r, t ); //在左子树中查找if( t ) return; //如果已在左子树中找到,便不必在右子树中查找Parent_PreOrder( curroot->right, r, t ); // 在右子树中查找}}template <class T>BinaryTreeNode<T> * BinaryTree<T>::LeftSibling( BinaryTreeNode<T> *current )//返回当前结点的左兄弟{BinaryTreeNode<T> *temp = Parent(current); //先找到给定结点的双亲if( !temp->left || current == temp->left )//双亲的左孩子若不是结点本身,则是结点的左兄弟{cout << "This node doesn't have a leftsibling!\n";exit(0);}return temp->left;}template <class T>BinaryTreeNode<T> * BinaryTree<T>::RightSibling( BinaryTreeNode<T> *current )//返回当前结点的右兄弟{BinaryTreeNode<T> *temp = Parent(current); //先找到给定结点的双亲if( !temp->right || current == temp->right )//双亲的右孩子若不是结点本身,则是结点的右兄弟{cout << "This node doesn't have a rightsibling!\n";exit(0);}return temp->right;}template < class T >void BinaryTree< T >::DeleteBinaryTree(BinaryTreeNode< T > * root) //删除二叉树或其子树{if(root == NULL) return; //判断是否为空树,若为空,则返回DeleteBinaryTree( root->left ); //递归删除左子树DeleteBinaryTree( root->right ); //递归删除右子树delete root; //删除根结点cout << "One node deleted!\n";root = NULL; //根结点置为空}template < class T >void BinaryTree< T >::PreOrder(BinaryTreeNode< T > * root) //先序遍历二叉树或其子树{if(root == NULL) //判断是否为空树,若为空,则返回return;visit(root->value()); //访问根结点PreOrder(root->leftchild()); //先序遍历左子树PreOrder(root->rightchild()); //先序遍历右子树}template < class T >void BinaryTree< T >::PreOrderWithoutRecusion(BinaryTreeNode< T > * root)//非递归先序遍历二叉树或其子树{stack< BinaryTreeNode< T > * >tStack;BinaryTreeNode< T > * pointer = root; //保存输入参数while(!tStack.empty()||pointer){if(pointer){visit(pointer->value()); //访问当前结点tStack.push(pointer); //当前结点地址入栈pointer = pointer->leftchild(); //当前链接结构指向左孩子}else{ //左子树访问完毕,转向访问右子树pointer = tStack.top(); //当前链接结构指向栈顶的元素tStack.pop(); //栈顶元素出栈pointer = pointer->rightchild(); //指向右孩子}}}template < class T >void BinaryTree< T >::InOrder(BinaryTreeNode< T > * root) //中序遍历二叉树或其子树{if(root == NULL) //判断是否为空树,若为空,则返回return;InOrder(root->leftchild()); //中序遍历左子树visit(root->value()); //访问根结点InOrder(root->rightchild()); //中序遍历右子树}template < class T >void BinaryTree< T >::InOrderWithoutRecusion(BinaryTreeNode< T > * root)//非递归中序遍历二叉树或其子树{stack< BinaryTreeNode< T > * >tStack;BinaryTreeNode< T > * pointer = root;while(!tStack.empty()||pointer){if(pointer){tStack.push(pointer); //当前结点地址入栈pointer = pointer->leftchild(); //当前链接结构指向左孩子}else{ //左子树访问完毕,转向访问右子树pointer = tStack.top(); //当前链接结构指向栈顶的元素visit(pointer->value()); //访问当前结点pointer = pointer->rightchild(); //指向右孩子tStack.pop(); //栈顶元素出栈}}}template < class T >void BinaryTree< T >::PostOrder(BinaryTreeNode< T > * root) //后序遍历二叉树或其子树{if(root == NULL) //判断是否为空树,若为空,则返回return;PostOrder(root->leftchild()); //后序遍历左子树PostOrder(root->rightchild()); //后序遍历右子树visit(root->value()); //访问根结点}enum Tag{L,R};template < class T >class StackNode{public:BinaryTreeNode< T > * pointer;Tag tag;};template < class T >void BinaryTree< T >::PostOrderWithoutRecusion(BinaryTreeNode< T > * root)//非递归后序遍历二叉树或其子树{stack< StackNode< T > >tStack;StackNode< T >Node;BinaryTreeNode< T > * pointer = root;do{while(pointer != NULL){ //将左子树中的结点加Tag=L后压入栈中Node.pointer = pointer;Node.tag = L;tStack.push(Node);pointer = pointer->leftchild();}Node = tStack.top(); //栈顶元素出栈tStack.pop();pointer = Node.pointer;if(Node.tag == R){ //如果从右子树回来visit(pointer->value()); //访问当前结点pointer = NULL; //置pointer为空,以继续弹栈}else{ //如果从左子树回来Node.tag = R; //标志域置为R,进入右子树tStack.push(Node);pointer = pointer->rightchild();}}while(!tStack.empty()||pointer);}template < class T >void BinaryTree< T >::CreateTree(BinaryTreeNode< T > * &r) //根据先序遍历序列构造二叉树{int ch;cin >> ch;if(ch == 0)r = NULL;else{ //读入非0数r = new BinaryTreeNode< T >(ch); //生成结点CreateTree(r->left); //构造左子树CreateTree(r->right); //构造右子树}}template < class T >void BinaryTree< T >::LevelOrder(BinaryTreeNode< T > * root) //按层序遍历二叉树或其子树{queue< BinaryTreeNode< T > * >tQueue;BinaryTreeNode< T > * pointer = root;if(pointer)tQueue.push(pointer); //根结点入队列while(!tQueue.empty()){pointer = tQueue.front(); //获得队列首结点tQueue.pop(); //当前结点出队列visit(pointer->value()); //访问当前结点if(pointer->leftchild() != NULL)tQueue.push(pointer->leftchild()); //左子树入队列if(pointer->rightchild() != NULL)tQueue.push(pointer->rightchild()); //右子树入队列}}template <class T>BinaryTreeNode<T> * BinaryTree<T>::Search( T &t, BinaryTreeNode<T> *root ) //二叉树搜索{if( isEmpty() ) //判断是否为空,若为空树,则跳出函数{cout << "The tree is empty!\n";exit(0);}BinaryTreeNode<T> *temp = NULL;//初始化临时指针,temp用于保存最后查找到的结点地址Search_PreOrder( t, root, temp );if( !temp ) //未查找到对应结点,将返回NULLcout << t << " doesn't exist in the tree!\n";return temp;}template <class T>void BinaryTree<T>::Search_PreOrder( T &t, BinaryTreeNode<T> *root, BinaryTreeNode<T> *&temp )//运用先序遍历的思想查找给定数据所在结点{if( !root ) return; //判断是否为空树,若为空,则返回if( t == root->value()) //找到指定结点并用temp保存地址{temp = root;return;}Search_PreOrder( t, root->left, temp ); //递归左子树if( temp ) return; //如果已在左子树中找到,则返回temp Search_PreOrder( t, root->right, temp ); //递归右子树}int main(){BinaryTree<int> my_tree; //定义my_tree cout << "Create my tree :" << endl;my_tree.CreateTree(my_tree.Root()); //创建my_tree cout << "my_tree's PreOrder is ";my_tree.PreOrder(my_tree.Root()); //先序遍历cout << endl << "my_tree's PreOrderWithoutRecusion is ";my_tree.PreOrderWithoutRecusion(my_tree.Root());cout << endl << "my_tree's InOrder is ";my_tree.InOrder(my_tree.Root()); //中序遍历cout << endl << "my_tree's InOrderWithoutRecusion is ";my_tree.InOrderWithoutRecusion(my_tree.Root());cout << endl << "my_tree's PostOrder is ";my_tree.PostOrder(my_tree.Root()); //后序遍历cout << endl << "my_tree's PostOrderWithoutRecusion is ";my_tree.PostOrderWithoutRecusion(my_tree.Root());cout << endl << "my_tree's LevelOrder is ";my_tree.LevelOrder(my_tree.Root()); //层序遍历cout << endl;int SearchElement;cout << "Please input a value you'd like to search in your tree:\n";cin >> SearchElement; //输入搜索元素BinaryTreeNode<int> *temp = my_tree.Search(SearchElement,my_tree.Root());//临时指针储存搜索地址if(temp) //若为空,则不存在cout << "Your searchelement is " << temp->value() << endl;elsecout << "none\n";return 0;}实验结果:创建一颗二叉树: 52 47 36 9其先序遍历为:5273694,中序遍历为:7263954,后序遍历为:7693245,层序遍历为:5247369。