数据结构实验报告—二叉树
实验报告:二叉树

实验报告:二叉树第一篇:实验报告:二叉树实验报告二叉树一实验目的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 姓名:朱报龙成绩:_________实验七二叉树操作验证一、实验目的⑴ 掌握二叉树的逻辑结构;⑵ 掌握二叉树的二叉链表存储结构;⑶ 掌握基于二叉链表存储的二叉树的遍历操作的实现。
华科数据结构二叉树实验报告

华科数据结构二叉树实验报告一、实验目的本实验旨在通过实践操作,加深对数据结构中二叉树的理解,掌握二叉树的基本操作和应用。
二、实验内容1. 实现二叉树的创建和初始化。
2. 实现二叉树的插入操作。
3. 实现二叉树的删除操作。
4. 实现二叉树的查找操作。
5. 实现二叉树的遍历操作:前序遍历、中序遍历、后序遍历。
6. 实现二叉树的层次遍历。
7. 实现二叉树的销毁操作。
8. 进行实验测试,并分析实验结果。
三、实验步骤1. 创建二叉树的数据结构,包括节点的定义和指针的初始化。
2. 实现二叉树的创建和初始化函数,根据给定的数据构建二叉树。
3. 实现二叉树的插入操作函数,将新节点插入到二叉树的合适位置。
4. 实现二叉树的删除操作函数,删除指定节点,并保持二叉树的结构完整。
5. 实现二叉树的查找操作函数,根据给定的值查找对应的节点。
6. 实现二叉树的遍历操作函数,包括前序遍历、中序遍历、后序遍历。
7. 实现二叉树的层次遍历函数,按照层次顺序遍历二叉树。
8. 实现二叉树的销毁操作函数,释放二叉树的内存空间。
9. 编写测试程序,对上述函数进行测试,并分析实验结果。
四、实验结果与分析经过测试,实验结果如下:1. 创建和初始化函数能够正确构建二叉树,并初始化节点的值和指针。
2. 插入操作函数能够将新节点插入到二叉树的合适位置,并保持二叉树的结构完整。
3. 删除操作函数能够正确删除指定节点,并保持二叉树的结构完整。
4. 查找操作函数能够根据给定的值找到对应的节点。
5. 遍历操作函数能够按照指定的顺序遍历二叉树,并输出节点的值。
6. 层次遍历函数能够按照层次顺序遍历二叉树,并输出节点的值。
7. 销毁操作函数能够释放二叉树的内存空间,防止内存泄漏。
根据实验结果分析,二叉树的基本操作和应用都能够正常实现,达到了预期的效果。
五、实验总结通过本次实验,我进一步加深了对数据结构中二叉树的理解,并掌握了二叉树的基本操作和应用。
通过实践操作,我更加熟悉了二叉树的创建、插入、删除、查找和遍历等操作,同时也学会了如何进行层次遍历和销毁二叉树。
数据结构实验报告 二叉树

数据结构实验报告二叉树数据结构实验报告:二叉树引言:数据结构是计算机科学中的重要基础,它为我们提供了存储和组织数据的方式。
二叉树作为一种常见的数据结构,广泛应用于各个领域。
本次实验旨在通过实践,深入理解二叉树的概念、性质和操作。
一、二叉树的定义与性质1.1 定义二叉树是一种特殊的树结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树可以为空树,也可以是由根节点和左右子树组成的非空树。
1.2 基本性质(1)每个节点最多有两个子节点;(2)左子树和右子树是有顺序的,不能颠倒;(3)二叉树的子树仍然是二叉树。
二、二叉树的遍历2.1 前序遍历前序遍历是指首先访问根节点,然后按照先左后右的顺序遍历左右子树。
在实际应用中,前序遍历常用于复制一颗二叉树或创建二叉树的副本。
2.2 中序遍历中序遍历是指按照先左后根再右的顺序遍历二叉树。
中序遍历的结果是一个有序序列,因此在二叉搜索树中特别有用。
2.3 后序遍历后序遍历是指按照先左后右再根的顺序遍历二叉树。
后序遍历常用于计算二叉树的表达式或释放二叉树的内存。
三、二叉树的实现与应用3.1 二叉树的存储结构二叉树的存储可以使用链式存储或顺序存储。
链式存储使用节点指针连接各个节点,而顺序存储则使用数组来表示二叉树。
3.2 二叉树的应用(1)二叉搜索树:二叉搜索树是一种特殊的二叉树,它的左子树上的节点都小于根节点,右子树上的节点都大于根节点。
二叉搜索树常用于实现查找、插入和删除等操作。
(2)堆:堆是一种特殊的二叉树,它满足堆序性质。
堆常用于实现优先队列,如操作系统中的进程调度。
(3)哈夫曼树:哈夫曼树是一种带权路径最短的二叉树,常用于数据压缩和编码。
四、实验结果与总结通过本次实验,我成功实现了二叉树的基本操作,包括创建二叉树、遍历二叉树和查找节点等。
在实践中,我进一步理解了二叉树的定义、性质和应用。
二叉树作为一种重要的数据结构,在计算机科学中有着广泛的应用,对于提高算法效率和解决实际问题具有重要意义。
数据结构实验报告二二叉树实验

实验报告课程名称:数据结构
第 1 页共4 页
五、实验总结(包括心得体会、问题回答及实验改进意见,可附页)
这次实验主要是建立二叉树,和二叉树的先序、中序、后续遍历算法。
通过这次实验,我巩固了二叉树这部分知识,从中体会理论知识的重要性。
在做实验之前,要充分的理解本次实验的理论依据,这样才能达到事半功倍的效果。
如果在没有真正理解实验原理之盲目的开始实验,只会浪费时间和精力。
例如进行二叉树的遍历的时候,要先理解各种遍历的特点。
先序遍历是先遍历根节点,再依次先序遍历左右子树。
中序遍历是先中序遍历左子树,再访问根节点,最后中序遍历右子树。
而后序遍历则是先依次后续遍历左右子树,再访问根节点。
掌握了这些,在实验中我们就可以融会贯通,举一反三。
其次要根据不光要懂得代码的原理,还要对题目有深刻的了解,要明白二叉树的画法,在纸上先进行自我演练,对照代码验证自己写的正确性。
第 3 页共4 页
第 4 页共4 页。
[精品]【数据结构】二叉树实验报告
![[精品]【数据结构】二叉树实验报告](https://img.taocdn.com/s3/m/5d561ae96e1aff00bed5b9f3f90f76c661374c27.png)
[精品]【数据结构】二叉树实验报告二叉树实验报告一、实验目的:1.掌握二叉树的基本操作;2.理解二叉树的性质;3.熟悉二叉树的广度优先遍历和深度优先遍历算法。
二、实验原理:1.二叉树是一种树形结构,由n(n>=0)个节点组成;2.每个节点最多有两个子节点,称为左子节点和右子节点;3.二叉树的遍历分为四种方式:前序遍历、中序遍历、后序遍历和层次遍历。
三、实验环境:1.编程语言:C++;2.编译器:Dev-C++。
四、实验内容:1.定义二叉树节点结构体:struct BinaryTreeNode{int data; // 节点数据BinaryTreeNode *leftChild; // 左子节点指针BinaryTreeNode *rightChild; // 右子节点指针};2.初始化二叉树:queue<BinaryTreeNode *> q; // 使用队列存储节点q.push(root);int i = 1; // 创建子节点while (!q.empty() && i < length){BinaryTreeNode *node = q.front();q.pop();if (data[i] != -1) // 创建左子节点 {BinaryTreeNode *leftChild = new BinaryTreeNode;leftChild->data = data[i];leftChild->leftChild = nullptr;leftChild->rightChild = nullptr;node->leftChild = leftChild;q.push(leftChild);}i++;if (data[i] != -1) // 创建右子节点 {BinaryTreeNode *rightChild = new BinaryTreeNode;rightChild->data = data[i];rightChild->leftChild = nullptr;rightChild->rightChild = nullptr;node->rightChild = rightChild;q.push(rightChild);}i++;}return root;}3.前序遍历二叉树:五、实验结果:输入:int data[] = {1, 2, 3, 4, -1, -1, 5, 6, -1, -1, 7, 8};输出:前序遍历结果:1 2 4 5 3 6 7 8中序遍历结果:4 2 5 1 6 3 7 8后序遍历结果:4 5 2 6 8 7 3 1层次遍历结果:1 2 3 4 5 6 7 8通过本次实验,我深入理解了二叉树的性质和遍历方式,并掌握了二叉树的基本操作。
数据结构二叉树的实验报告

数据结构二叉树的实验报告数据结构二叉树的实验报告一、引言数据结构是计算机科学中非常重要的一个领域,它研究如何组织和存储数据以便高效地访问和操作。
二叉树是数据结构中常见且重要的一种,它具有良好的灵活性和高效性,被广泛应用于各种领域。
本实验旨在通过实际操作和观察,深入了解二叉树的特性和应用。
二、实验目的1. 理解二叉树的基本概念和特性;2. 掌握二叉树的创建、遍历和查找等基本操作;3. 通过实验验证二叉树的性能和效果。
三、实验过程1. 二叉树的创建在实验中,我们首先需要创建一个二叉树。
通过输入一系列数据,我们可以按照特定的规则构建一棵二叉树。
例如,可以按照从小到大或从大到小的顺序将数据插入到二叉树中,以保证树的有序性。
2. 二叉树的遍历二叉树的遍历是指按照一定的次序访问二叉树中的所有节点。
常见的遍历方式有前序遍历、中序遍历和后序遍历。
前序遍历是先访问根节点,然后再依次遍历左子树和右子树;中序遍历是先遍历左子树,然后访问根节点,最后再遍历右子树;后序遍历是先遍历左子树,然后遍历右子树,最后访问根节点。
3. 二叉树的查找二叉树的查找是指在二叉树中寻找指定的节点。
常见的查找方式有深度优先搜索和广度优先搜索。
深度优先搜索是从根节点开始,沿着左子树一直向下搜索,直到找到目标节点或者到达叶子节点;广度优先搜索是从根节点开始,逐层遍历二叉树,直到找到目标节点或者遍历完所有节点。
四、实验结果通过实验,我们可以观察到二叉树的特性和性能。
在创建二叉树时,如果按照有序的方式插入数据,可以得到一棵平衡二叉树,其查找效率较高。
而如果按照无序的方式插入数据,可能得到一棵不平衡的二叉树,其查找效率较低。
在遍历二叉树时,不同的遍历方式会得到不同的结果。
前序遍历可以用于复制一棵二叉树,中序遍历可以用于对二叉树进行排序,后序遍历可以用于释放二叉树的内存。
在查找二叉树时,深度优先搜索和广度优先搜索各有优劣。
深度优先搜索在空间复杂度上较低,但可能会陷入死循环;广度优先搜索在时间复杂度上较低,但需要较大的空间开销。
数据结构实验报告—二叉树

数据结构实验报告—二叉树数据结构实验报告—二叉树引言二叉树是一种常用的数据结构,它由节点和边构成,每个节点最多有两个子节点。
在本次实验中,我们将对二叉树的基本结构和基本操作进行实现和测试,并深入了解它的特性和应用。
实验目的1. 掌握二叉树的基本概念和特性2. 熟练掌握二叉树的基本操作,包括创建、遍历和查找等3. 了解二叉树在实际应用中的使用场景实验内容1. 二叉树的定义和存储结构:我们将首先学习二叉树的定义,并实现二叉树的存储结构,包括节点的定义和节点指针的表示方法。
2. 二叉树的创建和初始化:我们将实现二叉树的创建和初始化操作,以便后续操作和测试使用。
3. 二叉树的遍历:我们将实现二叉树的前序、中序和后序遍历算法,并测试其正确性和效率。
4. 二叉树的查找:我们将实现二叉树的查找操作,包括查找节点和查找最大值、最小值等。
5. 二叉树的应用:我们将探讨二叉树在实际应用中的使用场景,如哈夫曼编码、二叉搜索树等。
二叉树的定义和存储结构二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。
节点被表示为一个由数据和指向其左右子节点的指针组成的结构。
二叉树可以分为三类:满二叉树、完全二叉树和非完全二叉树。
二叉树可以用链式存储结构或顺序存储结构表示。
- 链式存储结构:采用节点定义和指针表示法,通过将节点起来形成一个树状结构来表示二叉树。
- 顺序存储结构:采用数组存储节点信息,通过计算节点在数组中的位置来进行访问和操作。
二叉树的创建和初始化二叉树的创建和初始化是二叉树操作中的基础部分。
我们可以通过手动输入或读取外部文件中的数据来创建二叉树。
对于链式存储结构,我们需要自定义节点和指针,并通过节点的方式来构建二叉树。
对于顺序存储结构,我们需要定义数组和索引,通过索引计算来定位节点的位置。
一般来说,初始化一个二叉树可以使用以下步骤:1. 创建树根节点,并赋初值。
2. 创建子节点,并到父节点。
3. 重复步骤2,直到创建完整个二叉树。
数据结构二叉树的实验报告

数据结构实验报告1. 实验目的和内容:掌握二叉树基本操作的实现方法2. 程序分析2.1存储结构链式存储2.程序流程2.3关键算法分析算法一:Create(BiNode<T>* &R,T data[],int i,int n)【1】算法功能:创建二叉树【2】算法基本思想:利用顺序存储结构为输入,采用先建立根结点,再建立左右孩子的方法来递归建立二叉链表的二叉树【3】算法空间时间复杂度分析:O(n)【4】代码逻辑:如果位置小于数组的长度则{ 创建根结点将数组的值赋给刚才创建的结点的数据域创建左子树,如果当前结点位置为i,则左孩子位置为2i创建右子树,如果当前结点位置为i,则右孩子位置为2i+1}否则R为空算法二:CopyTree(BiNode<T>*sR,BiNode<T>* &dR))【1】算法功能:复制构造函数【2】算法基本思想:按照先创建根结点,再递归创建左右子树的方法来实现。
【3】算法空间时间复杂度分析:O(n)【4】代码逻辑:如果源二叉树根结点不为空则{创建根结点调用函数自身,创建左子树调用函数自身,创建右子树}将该函数放在复制构造函数中调用,就可以实现复制构造函数算法三:PreOrder(BiNode<T>*R)【1】算法功能:二叉树的前序遍历【2】算法基本思想:这个代码用的是优化算法,提前让当前结点出栈。
【3】算法空间时间复杂度分析:O(n)【4】代码逻辑(伪代码)如果当前结点为非空,则{访问当前结点当前结点入栈将当前结点的左孩子作为当前结点}如果为空{则栈顶结点出栈则将该结点的右孩子作为当前结点}反复执行这两个过程,直到结点为空并且栈空算法四:InOrder(BiNode<T>*R)【1】算法功能:二叉树的中序遍历【2】算法基本思想:递归【3】算法空间时间复杂度分析:未知【4】代码逻辑:如果R为非空:则调用函数自身遍历左孩子访问该结点再调用自身访问该结点的右孩子算法五:LevelOrder(BiNode<T>*R)【1】算法功能:二叉树的层序遍历【2】算法基本思想:【3】算法空间时间复杂度分析:O(n)【4】代码逻辑(伪代码):如果队列不空{对头元素出队访问该元素若该结点的左孩子为非空,则左孩子入队;若该结点的右孩子为非空,则右孩子入队;}算法六:Count(BiNode<T>*R)【1】算法功能:计算结点的个数【2】算法基本思想:递归【3】算法空间时间复杂度分析:未知【4】代码逻辑:如果R不为空的话{调用函数自身计算左孩子的结点数调用函数自身计算右孩子的结点数}template<class T>int BiTree<T>::Count(BiNode<T>*R){if(R==NULL)return 0;else{int m=Count(R->lchild);int n=Count(R->rchild);return m+n+1;}}算法七:Release(BiNode<T>*R)【1】算法功能:释放动态内存【2】算法基本思想:左右子树全部释放完毕后再释放该结点【3】算法空间时间复杂度分析:未知【4】代码逻辑:调用函数自身,释放左子树调用函数自身,释放右子树释放根结点释放二叉树template<class T>void BiTree<T>::Release(BiNode<T>*R) {if(R!=NULL){Release(R->lchild);Release(R->rchild);delete R;}}template<class T>BiTree<T>::~BiTree(){Release(root);}int main(){BiTree<int> BTree(a,10);BiTree<int>Tree(BTree);BTree.PreOrder(BTree.root);cout<<endl;Tree.PreOrder(Tree.root);cout<<endl;BTree.InOrder(BTree.root);cout<<endl;Tree.InOrder(Tree.root);cout<<endl;BTree.PostOrder(BTree.root);cout<<endl;Tree.PostOrder(Tree.root);cout<<endl;BTree.LevelOrder(BTree.root);cout<<endl;Tree.LevelOrder(Tree.root);cout<<endl;int m=BTree.Count(BTree.root);cout<<m<<endl;return 0;}3.测试数据:int a[10]={1,2,3,4,5};1 2 4 5 31 2 4 5 34 25 1 34 5 2 3 11 2 3 4 554.总结:4.1:这次实验大多用了递归的算法,比较好理解。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法与数据结构》课程实验报告一、实验目的1、实现二叉树的存储结构2、熟悉二叉树基本术语的含义3、掌握二叉树相关操作的具体实现方法二、实验内容及要求1. 建立二叉树2. 计算结点所在的层次3. 统计结点数量和叶结点数量4. 计算二叉树的高度5. 计算结点的度6. 找结点的双亲和子女7. 二叉树前序、中序、后序遍历的递归实现和非递归实现及层次遍历8. 二叉树的复制9. 二叉树的输出等三、系统分析(1)数据方面:该二叉树数据元素采用字符char 型,并且约定“ #”作为二叉树输入结束标识符。
并在此基础上进行二叉树相关操作。
(2)功能方面:能够实现二叉树的一些基本操作,主要包括:1. 采用广义表建立二叉树。
2. 计算二叉树高度、统计结点数量、叶节点数量、计算每个结点的度、结点所在层次。
3. 判断结点是否存在二叉树中。
4. 寻找结点父结点、子女结点。
5. 递归、非递归两种方式输出二叉树前序、中序、后序遍历。
6. 进行二叉树的复制。
四、系统设计(1)设计的主要思路二叉树是的结点是一个有限集合,该集合或者为空,或者是由一个根节点加上两棵分别称为左子树和右子树、互不相交的二叉树组成。
根据实验要求,以及课上老师对于二叉树存储结构、基本应用的讲解,同时课后研究书中涉及二叉树代码完成二叉树模板类,并将所需实现各个功能代码编写完成,在建立菜单对功能进行调试。
(2)数据结构的设计二叉树的存储结构有数组方式和链表方式。
但用数组来存储二叉树有可能会消耗大量的存储空间,故在此选用链表存储,提高存储空间的利用率。
根据二叉树的定义,二叉树的每一个结点可以有两个分支,分别指向结点的左、右子树。
因此,二叉树的结点至少应包括三个域,分别存放结点的数据,左子女结点指针,右子女结点指针。
这将有利于查找到某个结点的左子女与右子女,但要找到它的父结点较为困难。
该实验采取二叉链表存储二叉树中元素,具体二叉树链表表示如下图所示。
图1 二叉树的链表表示(3)基本操作的设计二叉树关键主要算法:利用广义表进行二叉树的建立。
该算法首先通过重载输入符号,在重载函数中调用CreatBinTree 函数,该函数有两个参数,第一个参数为输入流,用于传递用户输入的二叉树字符串,第二个参数则是二叉树的根结点root。
再通过栈操作是实现二叉树。
递归与非递归两种方式实现前序、中序、后序的遍历。
递归实现三种遍历的函数均只有一个参数即二叉树根节点root,递归结束条件则是结点为空。
当结点不为空时,根据三种遍历的方式不同而代码顺序不同。
其中前序遍历访问结点顺序是:根结点、左子树、右子树;中序遍历访问结点顺序是:左子树、根结点、右子树;后序遍历访问结点顺序是:左子树、右子树、根结点。
具体算法以及流程图见报告实验分析部分。
涉及二叉树性质的一些计算例如树的高度,结点所处层次,结点的度等。
在进行二叉树相关性质计算函数中参数为二叉树根节点root,再通过需要计算不同性质实现不同递归代码。
需要注意的是不同计算的递归结束条件不同对于结点父节点与子女结点的寻找。
对于结点父结点与子女结点的查找函数均有2 个参数,一个是二叉树根结点root 以及需要查找结点的数据域data。
具体实现方式是通过递归遍历每一个二叉树结点,当匹配到需要查找结点数据域时再进行对于该结点父结点或子女结点的输出,若未匹配成功则输出二叉树中不存在该结点。
五、编程环境与实验步骤(1)编程环境操作系统:Windows 操作系统;编程工具软件:Visual Studio 2017(2)实验步骤程序相关文件有:BinTreeNode.h、BinaryTree.h、Queue.h、SeqStack.h四个头文件以及主函数调试文件main.cpp(3)编译参数无编译参数,在Vs2017 或其他版本中新建项目然后将程序相关文件添加到解决方案中对应位置中调试即可。
六、实现代码#include "BinTreeNode.h"#include "SeqStack.h"#include "Queue.h"enum tag { L, R };extern int number;extern bool flag;extern bool flag1;extern bool flag2;template <class T>class BinaryTree {public :BinTreeNode <T> *root; // 二叉树根指针T RefValue; // 数据输入停止标志public :BinaryTree() {root = NULL;}BinaryTree( T value ) {root = NULL;RefValue = value ;BinaryTree( BinaryTree <T> &s) { root = Copy( s.root);} // 复制构造函数BinTreeNode <T> *Copy( BinTreeNode<T> * orignode );~BinaryTree(){ destroy(root); }void destroy( BinTreeNode<T> *& subTree );void Find_Father( BinTreeNode <T> *(& subTree ), T data ); // 找父节点void Find_Children( BinTreeNode <T> *(& subTree ), T data ); // 找子女节点void Find( BinTreeNode <T> *(& subTree ), T data ); // 查找结点int Height( BinTreeNode <T> * subTree ); // 返回树高度int Size( BinTreeNode <T> * subTree ); // 返回结点数void level( BinTreeNode <T> * subTree ); // 返回结点所在层次void Dujisuan( BinTreeNode <T> * subTree ); // 返回结点的度以及叶节点个数BinTreeNode <T> *getRoot() { return root; } // 取根bool Isempty() { return (root == NULL) ? true : false ; } // 判二叉树是否为空voiddgpreOrder( BinTreeNode <T> * subTree ); // 递归实现前序遍历void dginOrder( BinTreeNode <T> * subTree ); // 递归实现中序遍历void dgpostOrder( BinTreeNode <T> * subTree ); // 递归实现后序遍历void PrintBTree( BinTreeNode <T> * BT);void preOrder( BinTreeNode <T> * subTree ); // 非递归实现前序遍历void inOrder( BinTreeNode<T> * subTree ); // 非递归实现中序遍历void postOrder( BinTreeNode <T> * subTree ); // 非递归实现后序遍历void CreateBinTree( istream & in , BinTreeNode <T> *& BT); void Traverse( BinTreeNode <T> * subTree , ostream &out );template <class T>friend istream & operator>>( istream &in , BinaryTree <T> & Tree ); // 重载操作:输入template <class T>friend ostream & operator<<( ostream &out , BinaryTree <T> & Tree ); // 重载操作:输出};template <class T> void BinaryTree <T>::destroy( BinTreeNode <T> *& subTree ) {if ( subTree != NULL) {destroy( subTree ->leftChild); destroy( subTree ->rightChild); delete subTree;} }template <class T> void BinaryTree <T>::CreateBinTree( istream & in , BinTreeNode<T> *& BT) { SeqStack<BinTreeNode <T> *> s;BT = NULL; // 置空二叉树BinTreeNode <T> *p, *t; int k=0; T ch;in >> ch;while (ch != RefValue) {switch (ch) {case '(' :s.Push(p); k = 1; break ;case ')' :s.Pop(t); break ;case ',' :k = 2; break ; default :p = new BinTreeNode <T>(ch);if ( BT == NULL ) BT = p; else if (k == 1) { s.getTop(t); t->leftChild = p;} if (k==2) { s.getTop(t); t->rightChild = p;} } in >> ch;}} template <class T> void BinaryTree <T>::Traverse( BinTreeNode <T> * subTree, ostream &out) { if ( subTree != NULL) {out << subTree->data << " " ; Traverse( subTree ->leftChild, o ut );Traverse( subTree->rightChild, out);}}template <class T>void BinaryTree <T>::dginOrder( BinTreeNode<T> * subTree ) { if ( subTree != NULL){dginOrder( subTree ->leftChild); cout << subTree ->data << " " ; dginOrder( subTree ->rightChild);} } template <class T> void BinaryTree <T>::dgpostOrder( BinTreeNode <T> * subTree ) {if ( subTree != NULL) { dgpostOrder( subTree ->leftChild); dgpostOrder( subTree ->rightChild); cout << subTree ->data << " " ;}template <class T>void BinaryTree <T>::dgpreOrder( BinTreeNode <T> * subTree ) { if ( subTree != NULL) {cout << subTree ->data << " " ; dgpreOrder( subTree ->leftChild); dgpreOrder( subTree ->rightChild);}}template <class T>int BinaryTree <T>::Height( BinTreeNode<T> * subTree ) { if ( subTree == NULL)return 0;else {int i = Height( subTree ->leftChild);int j = Height( subTree ->rightChild); return (i < j) ? j + 1 : i + 1;}}template <class T>int BinaryTree <T>::Size( BinTreeNode<T> * subTree ) { if ( subTree == NULL)return 0;elsereturn 1 + Size( subTree ->leftChild) + Size( subTree ->rightChild);}template <class T>void BinaryTree <T>::PrintBTree( BinTreeNode <T> * BT) { if ( BT != NULL) {cout << BT->data;if ( BT->leftChild != NULL || BT->rightChild != NULL) {cout << "(" ;PrintBTree( BT->leftChild);cout << "," ;if ( BT->rightChild != NULL) PrintBTree( BT->rightChild);cout << " ) ";}}}template <class T>void BinaryTree <T>::preOrder( BinTreeNode <T> * subTree ) { SeqStack<BinTreeNode <T> *> S;BinTreeNode <T> *p = subTree ; BinTreeNode <T> *n = NULL;S.Push(n); while (p != NULL) { cout << p->data << " " ;if (p->rightChild != NULL) S.Push(p->rightChild); if (p->leftChild != NULL) p = p->leftChild; elseS.Pop(p);}} template <class T> void BinaryTree <T>::inOrder( BinTreeNode <T> * subTree ) {SeqStack<BinTreeNode <T> *> S;BinTreeNode <T> *p = root;BinTreeNode <T> *n = NULL; S.Push(n);do { while (p != NULL) {S.Push(p); p = p->leftChild;}if (!S.IsEmpty()) { S.Pop(p); if (p != n) { cout << p->data << " " ; p = p->rightChild;}}} while (p != NULL || !S.IsEmpty());} template <class T> struct stkNode {BinTreeNode <T> *ptr;tag ta;stkNode( BinTreeNode<T> * N = NULL) :ptr( N), ta( L) {} };template <class T>void BinaryTree <T>::postOrder( BinTreeNode<T> * subTree ) { SeqStack<stkNode <T>> S; stkNode <T> w;BinTreeNode <T> *p = root;do {while (p != NULL) {w.ptr = p; w.ta = L; S.Push(w);p = p->leftChild;} int continuel = 1; while (continuel && !S.IsEmpty()) { S.Pop(w); p = w.ptr; switch (w.ta) { case L:w.ta= R; S.Push(w);continuel = 0; p = p->rightChild; break ;case R:cout << p->data << " " ; break ;} }} while (!S.IsEmpty());cout << endl;} template <class T> istream &operator>> ( istream &in, BinaryTree <T>& Tree) {Tree .CreateBinTree( in , Tree .root); return in ;}template <class T> ostream &operator<< ( ostream & out, BinaryTree <T>& Tree) { out << " 二叉树的前序遍历" << endl;Tree .Traverse( Tree.root, out);out << endl; returnout;} template <class T>BinTreeNode<T> * BinaryTree <T>::Copy( BinTreeNode <T> * orignode ) { if ( orignode == NULL) return NULL;BinTreeNode <T> *temp = new BinTreeNode<T>; temp->data = orignode ->data;temp->leftChild = Copy( orignode ->leftChild); temp->rightChild = Copy( orignode ->rightChild); return temp;} template <class T> void BinaryTree <T>::level( BinTreeNode<T> * subTree ) {if ( subTree == NULL) return ;else {Queue<BinTreeNode <T> *> Q; BinTreeNode<T> *n; n = NULL;Q.EnQueue(subTree );Q.EnQueue(n);int level = 1;while (!Q.IsEmpty()) { BinTreeNode <T> *node; Q.DeQueue(node); if ( NULL == node) { if(Q.IsEmpty()) break ;level++; Q.EnQueue(n); continue ;}cout << "第" << level << "层结点:" << node->data << endl; if ( NULL != node->leftChild) Q.EnQueue(node->leftChild);if ( NULL != node->rightChild) Q.EnQueue(node->rightChild);}}}template <class T>void BinaryTree <T>::Dujisuan( BinTreeNode <T> * subTree ) {if ( subTree == NULL) return ;else {Queue<BinTreeNode <T> *> Q; int count = -1;Q.EnQueue(subTree );while (!Q.IsEmpty()) { BinTreeNode <T> *node; Q.DeQueue(node); if (node->leftChild != NULL && node->rightChild != NULL)count = 2;else if (node->leftChild == NULL && node->rightChild == NULL){count = 0; number++;}elsecount = 1;cout << node->data<< " 的度为:" <<count<< endl; if ( NULL != node->leftChild)Dujisuan(node->leftChild);if ( NULL != node->rightChild) Dujisuan(node->rightChild);}}}template <class T>void BinaryTree <T>::Find_Father( BinTreeNode<T> *(& subTree ), T data ) // 找父节点利用了递归的思想,基本结构还是前序遍历{if ( subTree == NULL)return ;if ( subTree->leftChild != NULL) // 当左孩子存在的时候才进行判断,否则程序出错{if ( subTree ->leftChild->data == data){cout << " 该节点的父结点是:" << subTree ->data<<endl;flag = true ;// 全局变量设置了一个标志flag=false ,如果找到父结点,则flag 赋值为true}}if ( subTree ->rightChild != NULL) // 如左子树所示{if ( subTree ->rightChild->data == data){cout << " 该节点的父结点是:" << subTree ->data<<endl; flag = true ;}}Find_Father( subTree ->leftChild, data );Find_Father( subTree ->rightChild, data );}template <class T>void BinaryTree <T>::Find_Children( BinTreeNode <T> *(& subTree ), T data )// 找子女节点利用了递归的思想,基本结构还是前序遍历{ if ( subTree == NULL)return ;else {if ( subTree ->data == data){flag2 = true ; // 全局变量设置了一个标志flag2=false ,如果找到父结点,则flag2赋值为 true}template <class T> void BinaryTree <T>::Find( BinTreeNode <T> *(&subTree ), T data) { if ( subTree == NULL)return ; else {if ( subTree ->data == data) flag1 = true ; else {Find( subTree ->leftChild, data ); Find( subTree ->rightChild,data );}}七、测试结果与说明菜单界面:if ( subTree ->leftChild != NULL) {cout << " 该节点的左子女结点是 :}if ( subTree ->rightChild != NULL) {cout << " 该节点的右子女结点是 :}if ( subTree ->leftChild == NULL) {cout << " 该节点的左子女结点为空}if ( subTree ->rightChild == NULL) {cout << " 该节点的右子女结点为空}}else {Find_Children( subTree ->leftChild, Find_Children( subTree ->rightChild,<< subTree ->leftChild->data << endl;<< subTree->rightChild->data << endl;<< endl;<< endl;data ); data );二叉树建立:二叉树高度计算:统计结点数量:结点度计算以及叶节点数量:结点所在层次计算:查找结点是否在树中:查找结点父结点:查找结点子女结点;二叉树输出结果(前序)三种方式(前序、中序、后序)输出二叉树(递归)三种方式(前序、中序、后序)输出二叉树(非递归)二叉树复制:八、实验分析(1)算法的性能分析二叉树涉及主要算法有利用广义表进行二叉树的建立、递归与非递归两种方式实现前序、中序、后序的遍历、二叉树性质的一些计算例如树的高度,结点所处层次,结点的度等。