数据结构二叉树实验
- 格式:docx
- 大小:387.80 KB
- 文档页数:56
数据结构二叉树遍历实验报告一、实验目的本次实验的主要目的是深入理解和掌握二叉树的三种遍历方式:前序遍历、中序遍历和后序遍历,并通过实际编程实现来加深对这些遍历算法的理解和应用能力。
二、实验环境本次实验使用的编程语言为 Python,开发工具为 PyCharm。
三、实验原理1、二叉树的定义二叉树是一种每个节点最多有两个子节点的树结构,分别称为左子节点和右子节点。
2、前序遍历前序遍历首先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。
3、中序遍历中序遍历首先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。
4、后序遍历后序遍历首先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。
四、实验步骤1、定义二叉树节点类```pythonclass TreeNode:def __init__(self, value):selfvalue = valueselfleft = Noneselfright = None```2、实现前序遍历函数```pythondef pre_order_traversal(root):if root is not None:print(rootvalue, end="")pre_order_traversal(rootleft)pre_order_traversal(rootright)```3、实现中序遍历函数```pythondef in_order_traversal(root):if root is not None:in_order_traversal(rootleft) print(rootvalue, end="")in_order_traversal(rootright)```4、实现后序遍历函数```pythondef post_order_traversal(root):if root is not None:post_order_traversal(rootleft) post_order_traversal(rootright) print(rootvalue, end="")```5、构建二叉树并进行遍历```python构建二叉树root = TreeNode(1) rootleft = TreeNode(2) rootright = TreeNode(3) rootleftleft = TreeNode(4) rootleftright = TreeNode(5)前序遍历print("前序遍历:")pre_order_traversal(root) print()中序遍历print("中序遍历:")in_order_traversal(root) print()后序遍历print("后序遍历:")post_order_traversal(root)print()```五、实验结果1、前序遍历结果:1 2 4 5 32、中序遍历结果:4 2 5 1 33、后序遍历结果:4 5 2 3 1六、结果分析1、前序遍历在前序遍历中,首先访问根节点,然后再访问左子树和右子树。
华科数据结构二叉树实验报告一、实验目的本实验旨在通过实践操作,加深对数据结构中二叉树的理解,掌握二叉树的基本操作和应用。
二、实验内容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 页。
[精品]【数据结构】二叉树实验报告二叉树实验报告一、实验目的: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. 引言二叉树是一种常见的数据结构,由节点(Node)和链接(Link)构成。
每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树在计算机科学中被广泛应用,例如在搜索算法中,二叉树可以用来快速查找和插入数据。
本实验旨在通过编写二叉树的基本操作来深入理解二叉树的特性和实现方式。
2. 实验内容2.1 二叉树的定义二叉树可以用以下方式定义:class TreeNode:def__init__(self, val):self.val = valself.left =Noneself.right =None每个节点包含一个值和两个指针,分别指向左子节点和右子节点。
根据需求,可以为节点添加其他属性。
2.2 二叉树的基本操作本实验主要涉及以下二叉树的基本操作:•创建二叉树:根据给定的节点值构建二叉树。
•遍历二叉树:将二叉树的节点按照特定顺序访问。
•查找节点:在二叉树中查找特定值的节点。
•插入节点:向二叉树中插入新节点。
•删除节点:从二叉树中删除特定值的节点。
以上操作将在下面章节详细讨论。
3. 实验步骤3.1 创建二叉树二叉树可以通过递归的方式构建。
以创建一个简单的二叉树为例:def create_binary_tree():root = TreeNode(1)root.left = TreeNode(2)root.right = TreeNode(3)root.left.left = TreeNode(4)root.left.right = TreeNode(5)return root以上代码创建了一个二叉树,根节点的值为1,左子节点值为2,右子节点值为3,左子节点的左子节点值为4,左子节点的右子节点值为5。
3.2 遍历二叉树二叉树的遍历方式有多种,包括前序遍历、中序遍历和后序遍历。
以下是三种遍历方式的代码实现:•前序遍历:def preorder_traversal(root):if root:print(root.val)preorder_traversal(root.left)preorder_traversal(root.right)•中序遍历:def inorder_traversal(root):if root:inorder_traversal(root.left)print(root.val)inorder_traversal(root.right)•后序遍历:def postorder_traversal(root):if root:postorder_traversal(root.left)postorder_traversal(root.right)print(root.val)3.3 查找节点在二叉树中查找特定值的节点可以使用递归的方式实现。
数据结构二叉树综合实验报告数据结构二叉树综合实验报告1.引言在计算机科学中,二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树具有广泛的应用场景,如在搜索算法、图形处理和编译器设计中等。
本报告旨在介绍我们进行的二叉树综合实验,包括实验目的、实验过程中的具体步骤和实验结果分析等。
2.实验目的本实验的主要目的是通过设计和实现二叉树的基本操作,加深对二叉树的理解,并掌握二叉树的基本算法和应用。
具体的实验目标包括:- 熟悉二叉树的基本概念和性质;- 掌握二叉树的创建、插入和删除操作;- 实现二叉树的遍历算法,包括前序、中序和后序遍历;- 实现二叉树的搜索功能;- 进行基于二叉树的排序实验。
3.实验步骤3.1 二叉树的创建首先,我们需要创建一个空的二叉树。
通过定义二叉树的节点结构和指针,可以动态地分配内存空间用于创建节点,并建立节点之间的连接关系。
3.2 节点的插入在已有的二叉树中,我们可以向其中插入新的节点。
插入操作通常涉及到比较节点的键值大小,然后根据比较结果决定插入新节点的位置。
3.3 节点的删除除了插入节点,我们也可能需要从二叉树中删除节点。
删除操作通常需要考虑节点的子节点情况,例如,被删除的节点是否有左子节点、右子节点或者同时存在。
3.4 二叉树的遍历二叉树的遍历操作可以按照不同的顺序进行,包括前序(根-左-右)、中序(左-根-右)和后序(左-右-根)遍历。
在实验中,我们需要实现这三种遍历算法,并观察它们的输出结果。
3.5 二叉树的搜索在已有的二叉树中,我们可根据节点的键值进行搜索操作。
通过比较键值,我们可以判断在左子树或右子树中进行进一步的搜索,直至找到目标节点或确定目标节点不存在于二叉树中。
3.6 基于二叉树的排序二叉树可以作为一种排序算法的基础结构。
在实验中,我们可以通过节点的插入操作构建一个包含数据集的二叉树,并通过中序遍历获取有序的数据。
课程实验报告课程名称:数据结构实验专业班级:学号:姓名:指导教师:报告日期:计算机科学与技术学院5 基于二叉存储结构实二叉树的基本操作 (3)1.1 问题描述 (3)1.2二叉树的操作系统设计 (3)1.2.1 系统总体设计 (3)1.2.2 有关常量和类型定义 (4)1.2.3 算法设计&算法分析 (5)1.3二叉树系统实现与测试 (9)1.3.1 系统实现 (9)1.3.2 系统测试 (47)1.4 实验小结 (55)5 基于二叉存储结构实二叉树的基本操作1.1 问题描述数据结构描述:在计算机科学中,二叉树是每个节点最多有两个子树的树结构。
通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。
二叉树常被用于实现二叉查找树和二叉堆,是一种非常重要的数据结构。
其结构如图:树根左孩子右孩子图-3.1 二叉树结构示意图本次试验要完成的顺序表和链式栈的相关操作。
算法有:1.构造二叉树数组2.创建二叉树3.清空二叉树4.判断二叉树是否为空5.返回指定元素的数据6.在指定位置插入和删除子树7.给指定元素结点赋值8.前序遍历二叉树9.中序遍历二叉树遍历10.后序便利二叉树11.层序遍历二叉树12.返回指定结点的左兄弟、右兄弟、双亲、左孩子和右孩子13.计算二叉树深度。
1.2二叉树的操作系统设计1.2.1 系统总体设计本系统包括22个模块的功能,包括栈的创建,销毁,清空,判断,计算长度,对指定元素操作,访问二叉树中元素等。
系统总体结构如图:图-3.2 函数调用关系1.2.2 有关常量和类型定义#define OK 1#define ERROR 0#define FALSE 0#define TRUE 1#define INIT_TREELINK_LENTH 20 #define INCREASE_LENTH 10#define INIT_STACK_LENTH 10初始化树根数组创建二叉树清空二叉树取根地址指定左孩子地址指定右孩子地址指定双亲地址主函数指定左兄弟地址指定右兄弟地址指定插入子树指定删除子树指定元素赋值指定元素取值typedef char Elemtype;typedef struct BiTreeNode //树结点定义{struct BiTreeNode *lChild;Elemtype data;int Node_Num;struct BiTreeNode *rChild;int flag;}BiTreeNode;typedef struct TreeLink //根数组{BiTreeNode *root;}TreeLink;typedef struct //定义顺序栈结构{BiTreeNode* stack[INIT_STACK_LENTH];int stack_top;}SqStack;typedef struct Qnode //定义队列结构{BiTreeNode* data;struct Qnode *next;}Qnode;typedef struct LinkQueue{Qnode *front;Qnode *rear;}LinkQueue;1.2.3 算法设计&算法分析1.构造树根数组创建一个树根数组,长度为INIT_ETRRLINK_LENTH,每一个元素的值为NULL 输入:数组首元素的地址输出:一个树根数组时间复杂度为常量阶,O(1);空间复杂度为常量阶,O(20)2.清空二叉树直接将root置为NULL输入:树根的地址输出:销毁成功OK或失败False时间复杂度:常量阶,O(1);空间复杂度:常量阶O(0)3.判空二叉树判断root是否指向,是的即为空,否则不为空输入:树根的地址输出:是否为空OK或者FALSE时间复杂度:常量阶O(1);空间复杂度:O(0)4.创建二叉树递归创建结点,没有孩子则输入#;返回树的指针并赋值个树根指针并赋给对应的树根指针;输入:无输出:一个二叉树的树根地址时间复杂度:线性阶O(n);空间复杂度:指数阶O(n2);6.计算二叉树深度输入:树根的地址输出:树的深度如果为空二叉树,则返回FALSE否则,对左右子树递归调用自身函数,最后比较左右子树的深度,取大加一时间复杂度:常量阶,O(n);空间复杂度:指数阶,O(n2)7.前序遍历二叉树用递归和非递归两种方式进行遍历;输入:树根地址输出:打印遍历结果如果为空,返回FALSE时间复杂度:线性阶,O(n);空间复杂度:线性阶,O(n)8.中遍历二叉树用递归和非递归两种方式进行遍历;输入:树根地址输出:打印遍历结果如果为空,返回FALSE时间复杂度:线性阶,O(n);空间复杂度:线性阶,O(n)9.后序遍历二叉树用递归和非递归两种方式进行遍历;输入:树根地址输出:打印遍历结果如果为空,返回FALSE时间复杂度:线性阶,O(n);空间复杂度:线性阶,O(n)10.层序遍历二叉树用一个队列保存结点地址,层序遍历输入:树根地址输出:屏幕打印遍历结果如果为空返回FALSE;时间复杂度:线性阶,O(n);空间复杂度:线性阶,O(n);11.返回根地址输入:树根地址数度:树根地址如果为空则返回FALSE;时间复杂度:常数阶,O(0);空间复杂度:常熟阶,O(0);12.返回指定结点左右孩子地址输入:树根地址,结点编号输出:对应结点的左(右)孩子地址如果为空则返回FALSE,如果没有左(右)孩子则返回NULL,如果没有输入的元素则打印提示;时间复杂度:线性阶,O(N),空间复杂度:线性阶O(n);13.返回指定结点左右兄弟地址输入:树根地址,结点编号输出:对应结点的左(右)兄弟地址如果为空则返回FALSE,如果没有左(右)兄弟则返回NULL,如果没有输入的元素则打印提示;时间复杂度:线性阶,O(N),空间复杂度:线性阶O(n);14.返回指定结点双亲地址输入:树根地址,结点编号输出:对应结点的双亲地址如果为空则返回FALSE,如果没有双亲则返回NULL,如果没有输入的元素则打印提示;时间复杂度:线性阶,O(N),空间复杂度:线性阶O(n);15.对指定结点赋值(取值)输入:树根指针,要赋的值输出:对应元素的值如果为空则返回FALSE时间复杂度:线性阶,O(N),空间复杂度:线性阶O(n);16.在指定位置插入(删除)子树输入:树根指针,要插入的指针输出:插入(删除)后的树根地址如果为空返回FALSE时间复杂度:线性阶,O(N),空间复杂度:线性阶O(n);1.3二叉树系统实现与测试1.3.1 系统实现1.编程环境的设置本次实验用的visual stdio 2012,语言使用C语言。
2.函数调用关系主程序,调用各个功能函数,在与栈有关的功能函数中调用对栈的相关操作函数,在与队列有关的功能函数中调用对队列的相关操作函数。
3.程序清单int InitQueue(LinkQueue *Q);int QueueEmpty(LinkQueue *Q);BiTreeNode* DeQueue(LinkQueue *Q);int EnQueue(LinkQueue *Q,BiTreeNode *e);int InitStack(SqStack *L);int StackEmpty(SqStack *L);int Push(SqStack *L,BiTreeNode *e);BiTreeNode* Pop(SqStack *L);TreeLink* InitBiTree();BiTreeNode* CreatBiTree(void);int Visit(Elemtype p);void RecursionPreOrderTraverse(BiTreeNode *T);void UnRecursionPreOrderTraverse(BiTreeNode *T) ;int BiTreeEmpty(BiTreeNode *T);int BiTreeDepth(BiTreeNode *T);void RecursionInOrderTraverse(BiTreeNode *T) ;void UnRecursionInOrderTraverse(BiTreeNode *T);void RecursionPostOrderTraverse(BiTreeNode *T);void UnRecursionPostOrderTraverse(BiTreeNode *T);BiTreeNode* RightSibling(BiTreeNode *T,int i); BiTreeNode* LeftSibling(BiTreeNode *T,int i); BiTreeNode* Parent(BiTreeNode *T,int i); BiTreeNode* LeftChlid(BiTreeNode *T,int i); BiTreeNode* RightChlid(BiTreeNode *T,int i);int InsertChlid(BiTreeNode *T,int i,BiTreeNode *c); int DeleteChild(BiTreeNode *T,int i);int Assign(BiTreeNode *T,int i,Elemtype data); Elemtype Value(BiTreeNode *T,int i);源代码:#include<stdio.h>#include<stdlib.h>#define OK 1#define ERROR 0#define FALSE 0#define TRUE 1#define INIT_TREELINK_LENTH 20#define INCREASE_LENTH 10#define INIT_STACK_LENTH 10typedef char Elemtype;typedef struct BiTreeNode //树结点定义{struct BiTreeNode *lChild;Elemtype data;int Node_Num;struct BiTreeNode *rChild;int flag;}BiTreeNode;typedef struct TreeLink //根数组{BiTreeNode *root;}TreeLink;typedef struct //定义顺序栈结构{BiTreeNode* stack[INIT_STACK_LENTH];int stack_top;}SqStack;typedef struct Qnode //定义队列结构{BiTreeNode* data;struct Qnode *next;}Qnode;typedef struct LinkQueue{Qnode *front;Qnode *rear;}LinkQueue;int InitQueue(LinkQueue *Q);int QueueEmpty(LinkQueue *Q);BiTreeNode* DeQueue(LinkQueue *Q);int EnQueue(LinkQueue *Q,BiTreeNode *e);int InitStack(SqStack *L);int StackEmpty(SqStack *L);int Push(SqStack *L,BiTreeNode *e);BiTreeNode* Pop(SqStack *L);TreeLink* InitBiTree();BiTreeNode* CreatBiTree(void);int Visit(Elemtype p);void RecursionPreOrderTraverse(BiTreeNode *T); void UnRecursionPreOrderTraverse(BiTreeNode *T) ; int BiTreeEmpty(BiTreeNode *T);int BiTreeDepth(BiTreeNode *T);void RecursionInOrderTraverse(BiTreeNode *T) ; void UnRecursionInOrderTraverse(BiTreeNode *T); void RecursionPostOrderTraverse(BiTreeNode *T); void UnRecursionPostOrderTraverse(BiTreeNode *T); BiTreeNode* RightSibling(BiTreeNode *T,int i); BiTreeNode* LeftSibling(BiTreeNode *T,int i); BiTreeNode* Parent(BiTreeNode *T,int i);BiTreeNode* LeftChlid(BiTreeNode *T,int i);BiTreeNode* RightChlid(BiTreeNode *T,int i);int InsertChlid(BiTreeNode *T,int i,BiTreeNode *c);int DeleteChild(BiTreeNode *T,int i);int Assign(BiTreeNode *T,int i,Elemtype data);Elemtype Value(BiTreeNode *T,int i);/******************************************************************** *************函数名称:InitQueue(LinkQueue *Q)函数功能:初始化一个空的队列函数参数:队列基址********************************************************************* *************/int InitQueue(LinkQueue *Q){Q->rear=(Qnode*)malloc(sizeof(Qnode));Q->front=Q->rear;Q->front->next=NULL;Q->rear->data=NULL;return OK;}/******************************************************************** *************函数名称:EnQueue(LinkQueue *Q,Elemtype e)初始条件:队列已经存在函数功能:插入一个新的元素结点到队尾函数参数:队列基址和插入的数据********************************************************************* *************/int EnQueue(LinkQueue *Q,BiTreeNode *e){Qnode *p;p=(Qnode *)malloc(sizeof(Qnode));if(!p){printf("\n\t\t生成结点失败!");return ERROR;}p->data=e;p->next=Q->front;Q->rear->next=p;Q->rear=p;return OK;}/******************************************************************** *************函数名称:QueueEmpty(LinkQueue *Q)初始条件:队列已经存在函数功能:判断队列是否为空队列,是则返回TRUE,否则返回FALSE函数参数:队列基址********************************************************************* *************/int QueueEmpty(LinkQueue *Q){if(Q->front==Q->rear){return TRUE;}else{return FALSE;}}/******************************************************************** *************函数名称:DeQueue(LinkQueue *Q)初始条件:队列已经存在函数功能:删除队列首结点函数参数:队列基址**********************************************************************************/BiTreeNode* DeQueue(LinkQueue *Q){Qnode *p;BiTreeNode *e;if(QueueEmpty(Q)){printf("\n\t\t空队列,不能出队列!");return ERROR;}p=Q->front;Q->front=p->next;e=p->next->data;free(p);return e;}/******************************************************************** ***************************************************************函数名称:InitStack(SqStack *L)操作结果:构造一个空栈********************************************************************* **************************************************************/int InitStack(SqStack *L){L->stack_top=-1;return OK;}/******************************************************************** **************************************************************函数名称:StackEmpty(SqStack *L)初始条件:栈已存在操作结果:如果栈为空返回TRUE,不为空返回FALSE********************************************************************* *************************************************************/int StackEmpty(SqStack *L){if(L->stack_top<0)return TRUE;elsereturn FALSE;}/******************************************************************** **************************************************************函数名称:Push(SqStack *L,BiTreeNode e)初始条件:栈已存在操作结果:插入一个元素作为新的栈顶(新的栈顶元素入栈)********************************************************************* *************************************************************/int Push(SqStack *L,BiTreeNode *e){if(L->stack_top<INIT_STACK_LENTH){L->stack_top+=1;L->stack[L->stack_top]=e;}elseprintf("\n\t\t数据溢出\n");return OK;}/******************************************************************** **************************************************************函数名称:Pop(SqStack *L,BiTreeNode e)初始条件:栈已存在且不为空操作结果:用e保存当前栈顶元素(栈顶元素出栈)********************************************************************* *************************************************************/ BiTreeNode* Pop(SqStack *L){BiTreeNode *e;if(L->stack_top!=-1){e=L->stack[L->stack_top];L->stack_top-=1;}elseprintf("\n\t\t栈已经为空\n");return e;}/******************************************************************** **************************函数名称:InitBiTree()函数功能:生成数目为初始长度棵树的根节点,并用一个根数组存储函数参数:无函数返回:存储根结点的数组基址********************************************************************* *************************/TreeLink* InitBiTree(){TreeLink *T;T=(TreeLink*)malloc(sizeof(TreeLink)*INIT_TREELINK_LENTH);return T;}/******************************************************************** ***********************函数名称:CreatBiTree(BiTreeNode *T)函数功能:用递归的方式建立二叉树函数参数:树根的左子树指针********************************************************************* ***********************/BiTreeNode * CreatBiTree(void){Elemtype c;BiTreeNode *T;int i;T=NULL;printf("\n\t\t输入结点数据,没有则输入#:\n\t\tc=");scanf("%1s",&c);if(c!='#'){printf("\n\t\t输入结点编号\n\t\ti=");scanf("%d",&i);T=(BiTreeNode*)malloc(sizeof(BiTreeNode));T->data=c;T->Node_Num=i;printf("\n\t\t对左孩子:");T->lChild=CreatBiTree();printf("\n\t\t对右孩子:");T->rChild=CreatBiTree();}return T;}/******************************************************************** *********************函数名称:ClearBiTree(BiTreeNode *T)函数功能:将二叉树置为空函数参数:树根指针********************************************************************* *********************/int ClearBiTree(BiTreeNode *T){T=NULL;return OK;}/******************************************************************** ********************函数名称:BiTreeEmpty(BiTreeNode *T)函数功能:判断一棵树是否为空,是则返回TRUE,否则返回FALSE函数参数:树根指针********************************************************************* ********************/int BiTreeEmpty(BiTreeNode *T){if(T==NULL)return TRUE;elsereturn FALSE;}/******************************************************************** ********************函数名称:Visit(Elemtype p)函数功能:访问结点数据函数参数:数据域标识符********************************************************************* ********************/int Visit(Elemtype p){printf("%4c",p);return OK;}/******************************************************************** ********************函数名称:RecursionPreOrderTraverse(BiTreeNode *T)函数功能:使用递归的方法对二叉树进行前序遍历初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/void RecursionPreOrderTraverse(BiTreeNode *T){if(T){printf("%4c",T->data);RecursionPreOrderTraverse(T->lChild);RecursionPreOrderTraverse(T->rChild);}}/******************************************************************** ********************函数名称:UnRecursionPreOrder(BiTreeNode *T)函数功能:使用非递归的方法对二叉树进行前序遍历初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/void UnRecursionPreOrderTraverse(BiTreeNode *T){BiTreeNode *p=T;SqStack s;InitStack(&s);while(p||!StackEmpty(&s)){if(p){Visit(p->data);Push(&s,p);p=p->lChild;}else{p=Pop(&s);p=p->rChild;}}}/******************************************************************** ********************函数名称:RecursionIndOrderTraverse(BiTreeNode *T)函数功能:使用递归的方法对二叉树进行中序遍历初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/void RecursionInOrderTraverse(BiTreeNode *T){if(T){RecursionInOrderTraverse(T->lChild);Visit(T->data);RecursionInOrderTraverse(T->rChild);}}/******************************************************************** ********************函数名称:UnRecursionIndOrderTraverse(BiTreeNode *T)函数功能:使用非递归的方法对二叉树进行中序遍历初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/void UnRecursionInOrderTraverse(BiTreeNode *T){BiTreeNode *p=T;SqStack s;InitStack(&s);while(p||!StackEmpty(&s)){if(p){Push(&s,p);p=p->lChild;}else{p=Pop(&s);Visit(p->data);p=p->rChild;}}}/******************************************************************** ********************函数名称:RecursionIndOrderTraverse(BiTreeNode *T)函数功能:使用递归的方法对二叉树进行后序遍历初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/void RecursionPostOrderTraverse(BiTreeNode *T){if(T){RecursionPostOrderTraverse(T->lChild);RecursionPostOrderTraverse(T->rChild);Visit(T->data);}}/******************************************************************** ********************函数名称:UnRecursionPostdOrderTraverse(BiTreeNode *T)函数功能:使用非递归的方法对二叉树进行后序遍历初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/void UnRecursionPostOrderTraverse(BiTreeNode *T){}/******************************************************************** ********************函数名称:LevelOrderTraverse(BiTreeNode *T)函数功能:对二叉树进行层序遍历初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/int LevelOrderTraverse(BiTreeNode *T){BiTreeNode *p;LinkQueue Q;InitQueue(&Q);EnQueue(&Q,T);while(!QueueEmpty(&Q)){p=DeQueue(&Q);Visit(p->data);if(p->lChild!=NULL)EnQueue(&Q,p->lChild);if(p->rChild!=NULL)EnQueue(&Q,p->rChild);}return OK;}/******************************************************************** ********************函数名称:Destory(BiTreeNode *T)函数功能:将二叉树所占的空间释放掉初始条件:二叉树已经存在函数参数:树根指针********************************************************************* ********************/int DestoryBiTree(BiTreeNode *T){BiTreeNode *p=T,*q=NULL;SqStack s;InitStack(&s);while(p||!StackEmpty(&s)){if(p){q=p;p=p->lChild;free(q);}else{p=Pop(&s);q=p;p=p->rChild;free(q);}}}/******************************************************************** ********************函数名称:Root(BiTreeNode *T)函数功能:返回二叉树的根初始条件:二叉树已经存在函数参数:树根指针********************************************************************* ********************/BiTreeNode* Root(BiTreeNode *T){if(BiTreeEmpty(T)){printf("\n\t\t二叉树为空,无根!");return NULL;}return (T->lChild);}/******************************************************************** ********************函数名称:SaveBiTree(BiTreeNode *T)函数功能:将二叉树写入磁盘初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/int SaveBiTree(BiTreeNode *T){FILE *out;BiTreeNode *p=T;SqStack s;if((out=fopen("f:\\BiTree.txt","wb"))==NULL){printf("\n\t\t文件打开失败!");return ERROR;}InitStack(&s);while(p||!StackEmpty(&s)){if(p){fwrite(p,sizeof(BiTreeNode),1,out);p=p->lChild;}else{p=Pop(&s);fwrite(p,sizeof(BiTreeNode),1,out);p=p->rChild;}}fclose(out);return OK;}/******************************************************************** ********************函数名称:BiTreeDepth(BiTreeNode *T)函数功能:返回树的深度初始条件:二叉树已经存在且不为空函数参数:树根指针********************************************************************* ********************/int BiTreeDepth(BiTreeNode *T){int depth,ldepth,rdepth;if(BiTreeEmpty(T)){return 0;}ldepth=BiTreeDepth(T->lChild);rdepth=BiTreeDepth(T->rChild);depth=ldepth>rdepth?ldepth:rdepth;depth+=1;return depth;}/******************************************************************** ********************函数名称:Value(BiTreeNode *T,int i)函数功能:返回e的值初始条件:二叉树已经存在且不为空函数参数:树根指针,某结点编号********************************************************************* ********************/Elemtype Value(BiTreeNode *T,int i){BiTreeNode *p=T;SqStack s;InitStack(&s);while(p||!StackEmpty(&s)){if(p){if(p->Node_Num==i)return p->data;else{Push(&s,p);p=p->lChild;}}else{p=Pop(&s);p=p->rChild;}}}/******************************************************************** ********************函数名称:Assign(BiTreeNode *T,int i,Elemtype value)函数功能:将e赋值为value初始条件:二叉树已经存在且不为空函数参数:树根指针,某结点编号,要被赋的值********************************************************************* ********************/int Assign(BiTreeNode *T,int i,Elemtype data){BiTreeNode *p=T;SqStack s;InitStack(&s);while(p||!StackEmpty(&s)){if(p){if(p->Node_Num==i){p->data=data;return OK;}else{Push(&s,p);p=p->lChild;}}else{p=Pop(&s);p=p->rChild;}}}/******************************************************************** ********************函数名称:DeleteChild(BiTreeNode *T,int i,int RL)函数功能:删除结点的孩子结点初始条件:二叉树已经存在且不为空函数参数:树根指针,要被删除孩子的节点的编号,删除标记符********************************************************************* ********************/int DeleteChild(BiTreeNode *T,int i){BiTreeNode *p,*q,*o,*r;SqStack s1,s2,s3;if(BiTreeEmpty(T)){printf("\n\t\t二叉树为空!");return ERROR;}p=T;InitStack(&s1);while(p||!StackEmpty(&s1)){if(p){if(p->Node_Num==i){if(p->lChild){q=p->lChild;InitStack(&s2);while(q||!StackEmpty(&s2)){if(q){Push(&s2,q);q=q->lChild;}else{q=Pop(&s2);printf("\n\t\t%c",q->data);o=q;q=q->rChild;free(o);}}}if(p->rChild){q=p->rChild;InitStack(&s3);while(q||!StackEmpty(&s3)){if(q){Push(&s3,q);q=q->lChild;}else{q=Pop(&s3);printf("\n\t\t%c",q->data);r=q;q=q->rChild;free(r);}}}else{printf("\n\t\t该结点没有孩子结点!\n");}p->lChild=NULL;p->rChild=NULL;return OK;}else{Push(&s1,p);p=p->lChild;}}else{p=Pop(&s1);p=p->rChild;}}return OK;}/******************************************************************** *******************************函数名称:InsertChlid(BiTreeNode *T,int i,int RL,BiTreeNode c)初始条件:二叉树T存在,n为某个结点的编号,LR为0或1,非空二叉树c与T不相交且右子树为空函数功能:根据LR为0或者1,插入c为T中编号为n的结点的左或右子树,编号为n的结点的原有左子树或右子树则为c的右子树初始条件:二叉树已经存在且不为空#函数参数:树根指针,要被插入右子树的节点指针,删除标记符********************************************************************* ******************************/int InsertChlid(BiTreeNode *T,int i,BiTreeNode *c){BiTreeNode *p,*q;SqStack s;if(BiTreeEmpty(T)){printf("\n\t\t二叉树为空!");return NULL;}p=T;InitStack(&s);while(p||!StackEmpty(&s)){if(p){if(p->Node_Num==i){if(!p->rChild)p->rChild=c;else if(!p->lChild)p->lChild=c;else{q=p->lChild;p->lChild=c;c->rChild=q;}}else{Push(&s,p);p=p->lChild;}return OK;}else{p=Pop(&s);p=p->rChild;}}return OK;}/******************************************************************** *******************************函数名称:Parent(BiTreeNode *T,int i)初始条件:二叉树T存在,e是T中某个结点的值函数功能:若e指向的是非根结点,则返回他的父母结点,则返回NULL。