实验6:二叉树及其应用
二叉树的算法应用
二叉树是一种非常常见的树形数据结构,它被广泛应用于各种算法和数据结构中。
以下是一些二叉树算法的应用:
1. 搜索二叉树:搜索二叉树是一种特殊的二叉树,它的每个节点都有一个值,并且每个节点的左子树中的所有节点的值都小于该节点的值,右子树中的所有节点的值都大于该节点的值。
搜索二叉树可以用于快速查找、插入和删除操作。
2. 平衡二叉树:平衡二叉树是一种自平衡的二叉搜索树,它通过在插入和删除节点时调整树的结构来保持平衡。
平衡二叉树可以保持树的深度较小,从而在查找、插入和删除操作时具有更好的时间复杂度。
3. 二叉堆:二叉堆是一种特殊的二叉树,它满足堆的性质,即每个节点的值都大于或等于其子节点的值。
二叉堆可以用于实现优先队列、堆排序等算法。
4. 哈夫曼编码:哈夫曼编码是一种用于无损数据压缩的算法,它使用二叉树来表示数据流中的频繁项。
哈夫曼编码可以有效地压缩数据,同时保持数据的可读性和可恢复性。
5. 决策树:决策树是一种基于二叉树的分类算法,它通过构建一棵二叉树来对数据进行分类。
决策树可以用于解决分类问题、预测问题等。
总之,二叉树是一种非常有用的数据结构,它可以用于实现各种算法和数据结构。
二叉树算法应用
二叉树算法应用引言:二叉树是一种常见的数据结构,它在计算机科学领域有着广泛的应用。
二叉树算法是对二叉树进行操作和处理的一系列方法和技巧。
本文将介绍二叉树算法的一些常见应用,并详细讨论它们的实现原理和使用场景。
一、二叉树的遍历二叉树的遍历是指按照某种顺序访问二叉树的所有节点。
常见的遍历方式有前序遍历、中序遍历和后序遍历。
前序遍历是先访问根节点,再遍历左子树和右子树;中序遍历是先遍历左子树,再访问根节点和右子树;后序遍历是先遍历左子树和右子树,再访问根节点。
这些遍历方式在实际应用中非常重要,例如在搜索树中查找某个节点、打印二叉树等场景都会用到。
二、二叉树的搜索二叉树的搜索是指在二叉树中查找特定节点的过程。
通过比较节点的值,可以判断目标节点在左子树还是右子树中,从而递归地进行搜索。
二叉搜索树是一种特殊的二叉树,它的左子树的所有节点的值都小于根节点的值,右子树的所有节点的值都大于根节点的值。
利用二叉搜索树的特性,可以快速地进行搜索操作,时间复杂度为O(logn)。
二叉搜索树的搜索在数据库索引、字典等场景中有广泛应用。
三、二叉树的插入和删除二叉树的插入和删除是对二叉树进行修改的操作。
插入操作是将新节点插入到合适的位置,保持二叉树的有序性。
删除操作是删除指定节点,并重新调整二叉树的结构。
在插入和删除操作中,需要考虑的情况比较复杂,例如插入的节点已存在、删除的节点有左右子树等。
通过合理地设计算法,可以高效地进行插入和删除操作,保持二叉树的平衡性。
四、二叉树的平衡二叉树的平衡是指左右子树的高度差不超过1。
平衡二叉树是一种特殊的二叉树,它的插入和删除操作可以保持树的平衡性,从而避免出现极端情况下的退化性能。
常见的平衡二叉树有红黑树、AVL 树、B树等。
平衡二叉树在高效查询和存储大量数据的场景中被广泛应用,例如数据库索引和文件系统。
五、二叉树的重建二叉树的重建是指根据给定的前序遍历和中序遍历结果,构建原二叉树的过程。
二叉树实验报告
二叉树实验报告二叉树是数据结构中最常见且重要的一种类型。
它由节点组成,每个节点最多有两个子节点,分别称为左节点和右节点。
通过连接这些节点,可以构建一个有序且具有层次结构的树形结构。
本实验报告将介绍二叉树的概念、特点以及常见的操作,同时介绍二叉树在实际应用中的一些典型案例。
一、二叉树的定义和特点二叉树是一种树形结构,它的每个节点至多只有两个子节点。
它的定义可以使用递归的方式进行描述:二叉树要么是一棵空树,要么由根节点和两棵分别称为左子树和右子树的二叉树组成。
二叉树的特点是每个节点最多只有两个子节点。
二、二叉树的创建和操作1.创建二叉树:二叉树可以通过两种方式来创建,一种是使用树的节点类来手动构建二叉树;另一种是通过给定的节点值列表,使用递归的方式构建二叉树。
2.遍历二叉树:二叉树的遍历有三种方式,分别是前序遍历、中序遍历和后序遍历。
a.前序遍历:先遍历根节点,再遍历左子树,最后遍历右子树。
b.中序遍历:先遍历左子树,再遍历根节点,最后遍历右子树。
c.后序遍历:先遍历左子树,再遍历右子树,最后遍历根节点。
3.查找节点:可以根据节点的值或者位置来查找二叉树中的节点。
4.插入节点:可以通过递归的方式在指定位置上插入一个新节点。
5.删除节点:可以通过递归的方式删除二叉树中的指定节点。
三、二叉树的应用案例二叉树在实际应用中有很多重要的用途,下面介绍几个典型的案例。
1.表示文件系统结构:文件系统可以使用二叉树来进行表示,每个文件或文件夹都可以看作是树中一个节点,节点之间的父子关系可以通过左右子树建立连接。
2.实现二叉树:二叉树是一种特殊的二叉树,它要求左子树上的节点值小于根节点的值,右子树上的节点值大于根节点的值。
这种树结构可以快速实现元素的插入、删除和查找等操作。
3.表达式求值:二叉树可以用来表示数学表达式,并且可以通过遍历来对表达式进行求值。
四、实验总结通过本次实验,我们深入了解了二叉树的定义和特点,学会了二叉树的创建和操作方法,以及了解了二叉树在实际应用中的一些典型案例。
实验六二叉树实验报告
实验四二叉树的操作班级:计算机1002班姓名:唐自鸿学号:201003010207 完成日期:2010.6.14 题目:对于给定的一二叉树,实现各种约定的遍历。
一、实验目的:(1)掌握二叉树的定义和存储表示,学会建立一棵特定二叉树的方法;(2)掌握二叉树的遍历算法(先序、中序、后序遍历算法)的思想,并学会遍历算法的递归实现和非递归实现。
二、实验内容:构造二叉树,再实现二叉树的先序、中序、后序遍历,最后统计二叉树的深度。
三、实验步骤:(一) 需求分析1. 二叉树的建立首先要建立一个二叉链表的结构体,包含根节点和左右子树。
因为树的每一个左右子树又是一颗二叉树,所以用递归的方法来建立其左右子树。
二叉树的遍历是一种把二叉树的每一个节点访问并输出的过程,遍历时根结点与左右孩子的输出顺序构成了不同的遍历方法,这个过程需要按照不同的遍历的方法,先输出根结点还是先输出左右孩子,可以用选择语句来实现。
2.程序的执行命令为:1)构造结点类型,然后创建二叉树。
2)根据提示,从键盘输入各个结点。
3)通过选择一种方式(先序、中序或者后序)遍历。
4)输出结果,结束。
(二)概要设计1.二叉树的二叉链表结点存储类型定义typedef struct Node{DataType data;struct Node *LChild;struct Node *RChild;}BitNode,*BitTree;2.建立如下图所示二叉树:void CreatBiTree(BitTree *bt)用扩展先序遍历序列创建二叉树,如果是当前树根置为空,否则申请一个新节点。
3.本程序包含四个模块1) 主程序模块:2)先序遍历模块3)中序遍历模块4)后序遍历模块4.模块调用关系:主程序模块(三)详细设计1.建立二叉树存储类型//==========构造二叉树=======void CreatBiTree(BitTree *bt)//用扩展先序遍历序列创建二叉树,如果是当前树根置为空,否则申请一个新节点//{char ch;ch=getchar();if(ch=='.')*bt=NULL;else{*bt=(BitTree)malloc(sizeof(BitNode));//申请一段关于该节点类型的存储空间(*bt)->data=ch; //生成根结点CreatBiTree(&((*bt)->LChild)); //构造左子树CreatBiTree(&((*bt)->RChild)); //构造右子树}}2. 编程实现以上二叉树的前序、中序和后序遍历操作,输出遍历序列1)先序遍历二叉树的递归算法如下:void PreOrder(BitTree root){if (root!=NULL){Visit(root ->data);PreOrder(root ->LChild); //递归调用核心PreOrder(root ->RChild);}}2)中序遍历二叉树的递归算法如下:void InOrder(BitTree root){if (root!=NULL){InOrder(root ->LChild);Visit(root ->data);InOrder(root ->RChild);}}3)后序遍历二叉树的递归算法如下:void PostOrder(BitTree root){if(root!=NULL){PostOrder(root ->LChild);PostOrder(root ->RChild);Visit(root ->data);}}4)计算二叉树的深度算法如下:int PostTreeDepth(BitTree bt) //求二叉树的深度{int hl,hr,max;if(bt!=NULL){hl=PostTreeDepth(bt->LChild); //求左子树的深度hr=PostTreeDepth(bt->RChild); //求右子树的深度max=hl>hr?hl:hr; //得到左、右子树深度较大者return(max+1); //返回树的深度}else return(0); //如果是空树,则返回0}四、调试分析及测试结果1. 进入演示程序后的显示主界面:请输入二叉树中的元素;先序、中序和后序遍历分别输出结果。
二叉树基础及应用
二叉树基础及应用二叉树是数据结构中的一种常见形式,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。
每个节点中包含了一个值以及指向其子节点的指针。
二叉树可以用于解决各种问题,具有广泛的应用。
下面将详细介绍二叉树的基础知识以及其应用。
首先,我们来了解一下二叉树的基本概念。
二叉树可以为空树,也可以由一个根节点及其子树组成。
根节点是二叉树的唯一入口,通过它可以找到其他节点。
每个节点的子树也是一个二叉树,即可以有左子树和右子树。
左子树中的节点小于根节点,右子树中的节点大于根节点。
这种有序性使得二叉树在搜索问题中非常高效。
在二叉树中,节点可以有不同的排列方式。
我们常见的有完全二叉树、满二叉树和平衡二叉树等。
完全二叉树是指除最后一层外,其他层的节点都是满的,并且最后一层的节点依次从左到右排列。
满二叉树是指每个节点都有两个子节点,除了叶子节点外,其他节点都没有子节点。
平衡二叉树是指左右子树的高度差不超过1的二叉树,它可以使得搜索、插入和删除的时间复杂度保持在O(log n)级别。
二叉树可以用于解决许多常见的问题。
其中一个常见的应用是二叉查找树。
二叉查找树是一种特殊的二叉树,它满足左子树中的所有节点的值小于根节点的值,右子树中的所有节点的值大于根节点的值。
通过这种排列方式,我们可以很快地找到某个值在二叉查找树中的位置。
在二叉查找树中进行搜索、插入和删除等操作的平均时间复杂度为O(log n),非常高效。
除了二叉查找树,二叉树还可以用于实现堆。
堆是一种特殊的二叉树,它满足父节点的值大于或小于子节点的值。
堆常常用于解决一些需要快速找到最大或最小元素的问题,特别是在优先队列中的应用。
通过使用堆,我们可以在常数时间内找到当前最大或最小的元素,并在对堆进行插入或删除操作时保持堆结构的性质。
此外,二叉树还可以用于构建哈夫曼树。
哈夫曼树是一种特殊的二叉树,它通过将出现频率较高的字符放在离根节点较近的位置,从而实现对字符进行编码的目的。
二叉树的原理和应用
二叉树的原理和应用1. 什么是二叉树二叉树是一种常见的树状数据结构,它由节点组成,每个节点最多有两个子节点。
每个节点分为左子节点和右子节点,它们分别表示节点的左子树和右子树。
2. 二叉树的基本特点•每个节点最多有两个子节点。
•左子节点比父节点小,右子节点比父节点大,这个条件称为二叉搜索树的性质。
3. 二叉树的基本操作对于二叉树,我们可以进行一些基本的操作,包括插入节点、删除节点、查找节点等。
3.1 插入节点在二叉树中插入新节点的方法如下: - 如果树为空,则新节点为根节点。
- 如果新节点的值小于当前节点的值,将新节点插入到当前节点的左子树。
- 如果新节点的值大于当前节点的值,将新节点插入到当前节点的右子树。
3.2 删除节点在二叉树中删除节点的方法如下: - 如果待删除的节点是叶子节点,直接删除即可。
- 如果待删除的节点只有一个子节点,将其子节点移到待删除节点的位置。
- 如果待删除的节点有两个子节点,找到右子树的最小节点(或左子树的最大节点),将其值复制到待删除节点,然后删除这个最小节点(或最大节点)。
3.3 查找节点在二叉树中查找节点的方法如下: - 从根节点开始,若待查找的节点等于当前节点的值,则返回当前节点。
- 若待查找的节点小于当前节点的值,则继续在当前节点的左子树中查找。
- 若待查找的节点大于当前节点的值,则继续在当前节点的右子树中查找。
4. 二叉树的应用二叉树作为一种重要的数据结构,被广泛应用于多个领域。
4.1 网络路由在计算机网络中,二叉树用于确定数据包的路由。
每个节点表示网络节点,每个子节点表示网络连接的下一个节点,通过不断判断数据包的目标地址来选择合适的子节点进行转发。
4.2 数据库索引在数据库中,二叉树被用于加速数据的检索。
通过将数据存储在二叉树中,可以快速地检索特定值。
4.3 二叉排序树二叉排序树也称为二叉搜索树,它具有以下特点: - 对于任意节点,左子树中的值都小于它的值,右子树中的值都大于它的值。
数据结构实验报告—二叉树
数据结构实验报告—二叉树数据结构实验报告—二叉树引言二叉树是一种常用的数据结构,它由节点和边构成,每个节点最多有两个子节点。
在本次实验中,我们将对二叉树的基本结构和基本操作进行实现和测试,并深入了解它的特性和应用。
实验目的1. 掌握二叉树的基本概念和特性2. 熟练掌握二叉树的基本操作,包括创建、遍历和查找等3. 了解二叉树在实际应用中的使用场景实验内容1. 二叉树的定义和存储结构:我们将首先学习二叉树的定义,并实现二叉树的存储结构,包括节点的定义和节点指针的表示方法。
2. 二叉树的创建和初始化:我们将实现二叉树的创建和初始化操作,以便后续操作和测试使用。
3. 二叉树的遍历:我们将实现二叉树的前序、中序和后序遍历算法,并测试其正确性和效率。
4. 二叉树的查找:我们将实现二叉树的查找操作,包括查找节点和查找最大值、最小值等。
5. 二叉树的应用:我们将探讨二叉树在实际应用中的使用场景,如哈夫曼编码、二叉搜索树等。
二叉树的定义和存储结构二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。
节点被表示为一个由数据和指向其左右子节点的指针组成的结构。
二叉树可以分为三类:满二叉树、完全二叉树和非完全二叉树。
二叉树可以用链式存储结构或顺序存储结构表示。
- 链式存储结构:采用节点定义和指针表示法,通过将节点起来形成一个树状结构来表示二叉树。
- 顺序存储结构:采用数组存储节点信息,通过计算节点在数组中的位置来进行访问和操作。
二叉树的创建和初始化二叉树的创建和初始化是二叉树操作中的基础部分。
我们可以通过手动输入或读取外部文件中的数据来创建二叉树。
对于链式存储结构,我们需要自定义节点和指针,并通过节点的方式来构建二叉树。
对于顺序存储结构,我们需要定义数组和索引,通过索引计算来定位节点的位置。
一般来说,初始化一个二叉树可以使用以下步骤:1. 创建树根节点,并赋初值。
2. 创建子节点,并到父节点。
3. 重复步骤2,直到创建完整个二叉树。
数据结构二叉树实验报告
数据结构二叉树实验报告二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。
本文将介绍二叉树的定义、基本操作以及一些常见的应用场景。
一、二叉树的定义和基本操作二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。
一个节点的左子节点称为左子树,右子节点称为右子树。
二叉树的示意图如下:```A/ \B C/ \D E```在二叉树中,每个节点可以有零个、一个或两个子节点。
如果一个节点没有子节点,我们称之为叶子节点。
在上面的示例中,节点 D 和 E 是叶子节点。
二叉树的基本操作包括插入节点、删除节点、查找节点和遍历节点。
插入节点操作可以将一个新节点插入到二叉树中的合适位置。
删除节点操作可以将一个指定的节点从二叉树中删除。
查找节点操作可以在二叉树中查找指定的节点。
遍历节点操作可以按照一定的顺序遍历二叉树中的所有节点。
二、二叉树的应用场景二叉树在计算机科学中有着广泛的应用。
下面将介绍一些常见的应用场景。
1. 二叉搜索树二叉搜索树是一种特殊的二叉树,它的每个节点的值都大于其左子树中的节点的值,小于其右子树中的节点的值。
二叉搜索树可以用来实现快速的查找、插入和删除操作。
它在数据库索引、字典等场景中有着重要的应用。
2. 堆堆是一种特殊的二叉树,它的每个节点的值都大于或小于其子节点的值。
堆可以用来实现优先队列,它在任务调度、操作系统中的内存管理等场景中有着重要的应用。
3. 表达式树表达式树是一种用来表示数学表达式的二叉树。
在表达式树中,每个节点可以是操作符或操作数。
表达式树可以用来实现数学表达式的计算,它在编译器、计算器等场景中有着重要的应用。
4. 平衡二叉树平衡二叉树是一种特殊的二叉树,它的左子树和右子树的高度差不超过1。
平衡二叉树可以用来实现高效的查找、插入和删除操作。
它在数据库索引、自平衡搜索树等场景中有着重要的应用。
三、总结二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。
本文介绍了二叉树的定义、基本操作以及一些常见的应用场景。
二叉树 实验报告
二叉树实验报告二叉树实验报告引言:二叉树是一种常见的数据结构,它由节点和边组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。
在本次实验中,我们将探索二叉树的基本概念、特性以及应用。
一、二叉树的定义与性质1.1 二叉树的定义二叉树是一种递归定义的数据结构,它可以为空,或者由一个根节点和两个二叉树组成,分别称为左子树和右子树。
1.2 二叉树的性质(1)每个节点最多有两个子节点,分别称为左子节点和右子节点。
(2)左子树和右子树也是二叉树。
(3)二叉树的子树之间没有关联性,它们是相互独立的。
二、二叉树的遍历方式2.1 前序遍历前序遍历是指先访问根节点,然后按照先左后右的顺序遍历左子树和右子树。
2.2 中序遍历中序遍历是指先遍历左子树,然后访问根节点,最后遍历右子树。
2.3 后序遍历后序遍历是指先遍历左子树,然后遍历右子树,最后访问根节点。
2.4 层次遍历层次遍历是指按照从上到下、从左到右的顺序遍历二叉树的每个节点。
三、二叉树的应用3.1 二叉搜索树二叉搜索树是一种特殊的二叉树,它的每个节点的值大于其左子树的所有节点的值,小于其右子树的所有节点的值。
这种特性使得二叉搜索树可以高效地进行查找、插入和删除操作。
3.2 哈夫曼树哈夫曼树是一种带权路径长度最短的二叉树,它常用于数据压缩中。
哈夫曼树的构建过程是通过贪心算法,将权值较小的节点放在离根节点较远的位置,从而实现最优编码。
3.3 表达式树表达式树是一种用于表示数学表达式的二叉树,它的叶节点是操作数,而非叶节点是操作符。
通过对表达式树的遍历,可以实现对表达式的求值。
结论:通过本次实验,我们对二叉树的定义、性质、遍历方式以及应用有了更深入的了解。
二叉树作为一种重要的数据结构,在计算机科学和算法设计中发挥着重要的作用。
在今后的学习和工作中,我们应该进一步探索二叉树的高级应用,并灵活运用于实际问题的解决中。
二叉树的基本操作与应用
二叉树的基本操作与应用二叉树的基本操作与应用。
二叉树是一种特殊的树结构,它的每个节点最多只能有两个子节点。
在实际应用中,二叉树具有广泛的应用,例如在计算机科学中的数据结构与算法、人工智能领域中的决策树等。
本文将以二叉树的基本操作与应用为主题,一步一步回答相关问题。
一、什么是二叉树?二叉树是由节点组成的层次结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。
它的特点是每个子节点都是唯一的,没有重复的子节点。
通过将这些节点按照一定的规则进行连接,就形成了一棵二叉树。
二、二叉树的基本操作有哪些?二叉树的基本操作包括创建二叉树、遍历二叉树、插入节点、删除节点等。
下面将分别对这些操作进行介绍。
1. 创建二叉树:创建二叉树的方法有多种,最常见的方法是使用递归或迭代的方式进行创建。
例如,可以使用递归的方式根据给定的数组创建一棵二叉树。
2. 遍历二叉树:遍历二叉树是指按照一定的顺序访问二叉树中的每一个节点。
常见的遍历方式有三种:前序遍历、中序遍历和后序遍历。
前序遍历的顺序是先访问根节点,然后访问左子树,最后访问右子树。
中序遍历的顺序是先访问左子树,然后访问根节点,最后访问右子树。
后序遍历的顺序是先访问左子树,然后访问右子树,最后访问根节点。
3. 插入节点:插入节点是指在二叉树中新增一个节点。
插入节点的方法有多种,最常见的是在二叉树的某个位置插入一个节点。
例如,可以在二叉树的最后一层的某个位置插入一个节点。
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.顺序存储七、思考讨论题或体会或对改进实验的建议通过这次实验,我掌握了二叉树的顺序存储和链式存储,体会了二叉树的存储结构的特性,掌握了二叉树的树上相关操作。
实验6 二叉树及其应用
实验6 二叉树及其应用1.实验目的1)了解二叉树的特点、掌握二叉树的主要存储结构。
2)掌握二叉树的基本操作,能针对二叉树的具体应用选择相应的存储结构。
3)掌握递归算法的设计方法。
2.实验内容(1)二叉链表表示二叉树,建立一棵二叉树,实现下列基本操作,通过数据测试每个操作的正确性,包括:1. CreateBinTree(&T):按扩展二叉树的先序遍历结果构造二叉树。
2. BinTreeEmpty(T): 判断一棵二叉树是否为空树。
3. PreOrderTraverse(T): 先序遍历二叉树T,并输出节点序列。
4. InOrderTraverse(T): 中序遍历二叉树T,并输出节点序列。
5. PostOrderTraverse(T):后序遍历二叉树T,并输出节点序列。
6. LevelOrderTraverse(T):层次遍历二叉树T,并输出节点序列。
7. Value(T,e):查找值为e的节点,并返回该节点的地址。
8. BinTreeDepth(T):返回二叉树的深度。
9. Parent(T,e):查找二叉树T中值为e的节点的双亲,若e为根节点,操作失败。
10. LeftChild(T,e):查找二叉树T中值为e的节点的左孩子,若e没有左孩子,则操作失败。
11.RightChild(T,e):查找二叉树T中值为e的节点的右孩子,若e没有右孩子,则操作失败。
12. CountNode(T):计算二叉树中节点的个数。
13. Leaf(T): 计算二叉树中叶子节点的个数。
14. OneChild(T): 计算二叉树中度为1的节点个数。
3.实验要求(1)上机前编写实验源程序(要求手写,不允许打印),上机前老师检查,没有预先编写实验程序的同学不允许上实验课,按旷课一次处理。
旷课次数超过2次的同学实验成绩不及格,且没有补考资格。
(2)用一切你能想到的办法解决遇到的问题,培养解决问题的能力。
(3)实验报告(于下次实验时交)报告内容包括:实验目的、实验内容、实验代码、实验输入输出结果以及实验体会供五部分。
二叉树实现及应用实验报告
二叉树实现及应用实验报告实验名称:二叉树实现及应用实验目的:1. 实现二叉树的创建、插入和删除操作。
2. 学习二叉树的遍历方法,并能够应用于实际问题。
3. 掌握二叉树在数据结构和算法中的一些常用应用。
实验内容:1. 实现二叉树的创建、插入和删除操作,包括二叉树的构造函数、插入函数和删除函数。
2. 学习二叉树的三种遍历方法:前序遍历、中序遍历和后序遍历,并应用于实际问题。
3. 掌握二叉树的一些常用应用,如二叉搜索树、平衡二叉树和哈夫曼树等。
实验步骤:1. 创建二叉树的结构体,包括树节点和树的根节点。
2. 实现二叉树的构造函数,用于创建二叉树的根节点。
3. 实现二叉树的插入函数,用于将元素插入到二叉树中的合适位置。
4. 实现二叉树的删除函数,用于删除二叉树中的指定元素。
5. 学习并实现二叉树的前序遍历、中序遍历和后序遍历函数。
6. 运用二叉树的遍历方法解决实际问题,如查找二叉树中的最大值和最小值。
7. 学习并应用二叉搜索树、平衡二叉树和哈夫曼树等常用二叉树结构。
实验结果:1. 成功创建、插入和删除二叉树中的元素,实现了二叉树的基本操作。
2. 正确实现了二叉树的前序遍历、中序遍历和后序遍历,并能够正确输出遍历结果。
3. 通过二叉树的遍历方法成功解决了实际问题,如查找二叉树中的最大值和最小值。
4. 学习并熟练应用了二叉搜索树、平衡二叉树和哈夫曼树等常用二叉树结构,丰富了对二叉树的理解。
实验分析:1. 二叉树是一种重要的数据结构,具有较好的数据存储和查找性能,广泛应用于计算机科学和算法领域。
2. 通过实验,我们深入了解了二叉树的创建、插入和删除操作,以及前序遍历、中序遍历和后序遍历的原理和应用。
3. 实际问题往往可以转化为二叉树的遍历问题进行求解,通过实验,我们成功应用了二叉树的遍历方法解决了实际问题。
4. 熟练掌握二叉搜索树、平衡二叉树和哈夫曼树的原理和应用,对于提高我们在数据结构和算法方面的设计能力具有重要意义。
实验六 二叉树及应用的实验
实验六二叉树及应用的实验【实验目的】掌握二叉树的左右链存储实现,二叉树的建立方法,二叉树的遍历算法,哈夫曼树的程序实现。
【实验说明】1、存储结构定义及库文件# include <stdio.h># include <stdlib.h># define TRUE 1# define FALSE 0#define Stack_Size 50typedef char DataType;typedef struct node {DataType data;struct node *lchild,*rchild;}BiTNode,*BiTree;2、建立二叉树void CreateBiTree(BiTree *bt ){ char ch;ch=getchar();if(ch=='.') *bt=NULL;else{*bt=(BiTree)malloc(sizeof(BiTNode));(*bt)->data=ch;CreateBiTree(&((*bt)->lchild));CreateBiTree(&((*bt)->rchild));}}3、先序递归遍历二叉树void PreOrder(BiTree root)//root指向二叉树根结点{ if(root!=NULL){printf("%c",root->data);PreOrder(root->lchild);PreOrder(root->rchild);}}4、中序非递归遍历二叉树void inorder(BiTree root){BiTNode *p;int top;BiTree S[Stack_Size];top=0;p=root;//printf("ZYZ\n");do{while(p!=NULL){if(top>Stack_Size-1) {printf("栈满\n");return;}else {top=top+1;S[top]=p;p=p->lchild;};}if (top!=0){p=S[top];top=top-1;printf("%c",p->data);p=p->rchild;}}while(p!=NULL||top!=0);}4、主控菜单处理调试程序void main( ){BiTree T=NULL;int xz=1;char ch;while(xz) {printf(" 二叉树的建立及遍历\n");printf("==========================\n");printf(" 1、建立二叉树存储结构\n");printf(" 2、二叉树的前序遍历(递归)\n");printf(" 3、二叉树的中序遍历(非递归)\n");printf(" 0、退出系统\n");printf("===========================\n");printf(" 请选择:0--3 ");scanf("%d",&xz);switch(xz){ case 0: printf("再见!\n");return;case 1: ch=getchar();printf("按扩展先序遍历序列输入二叉树各结点值:");CreateBiTree(&T);printf("\n二叉树的链式存储结构建立完成!\n");printf("\n");break;case 2: printf("二叉树先序遍历序列为:");if(T) PreOrder(T);else printf("\n空树");printf("\n");printf("\n");break;case 3: printf("二叉树中序遍历序列为:");inorder(T);printf("\n");break;}}return;}//main【实验内容】⑴二叉树的遍历算法(非递归实现先序遍历,用递归实现中序遍历,用非递归实现后序遍历,层次遍历)⑵二叉树采用二叉链表方式存储,找到二叉树中度为0的结点个数。
二叉树及其应用
改进算法
1. 根据给定的n个权值wl,w2,…,wn构成n棵k叉树的森林
F={T1,T2,…,Tn}。其中每棵k叉树Ti中都只有一个权 值为wi的根结点,其左右子树均空。进行第一次合并操作 选出最小的(n-2)mod(k-1)+2颗根节点权值最小的树进行合 并成一棵新树,该树根的权值为选出来的树的权值之和。 2. 在森林F中选出k棵根结点权值最小的树(当这样的树不止k 棵树时,可以从中任选出k棵),将这k棵树合并成一棵新 树,为了保证新树仍是k叉树,需要增加一个新结点作为新 树的根,并将所选的k棵树的根分别作为新根的孩子,将这 k个孩子的权值之和作为新树根的权值。 3. 对新的森林F重复(2),直到森林F中只剩下一棵树为止。这 棵树便是最优k叉树。
在堆中删除任意一个元素
这里说指的删除任意一个元素,是指在当前
堆中位置为w的元素。过程如下:首先把位 置w的元素和最后一个位置的元素交换,然 后删去最后一个位置,这样w上的元素就被 删除了。接着把位置w上的新元素不断下调, 直到满足堆的性质。
1 2 5 4
1 5
3
5
7
8
3
5
7
8
6
4
6
2
(1)当前要删除的节点是根节点的左儿子 1
由于每次要取出最小的两个节点。(一般做法是每
更新一次集合,重新排序,时间是O(n^2))。由 于n<=10000,不得不采用数据结构--堆进行优化。 解决方案 方法或要点 时间复杂度 可过数据
解决方案1 一般做法 解决方案2 堆
(n )
2
30%-50%
(n log n)
100%
任务
有n个任务,每个任务有一个截止完成的时间
二叉树操作及应用的原理
二叉树操作及应用的原理1. 什么是二叉树二叉树是一种特殊的树状数据结构,它的每个节点最多有两个子节点。
每个节点应至多有一个父节点,除了根节点,其他节点均有且只有一个父节点。
二叉树可以为空,也可以只有一个节点。
2. 二叉树的基本操作2.1 插入节点在二叉树中插入节点可以有多种方式,以下是在二叉搜索树中插入节点的过程:1. 首先比较要插入的节点值与当前节点值大小关系。
2. 如果要插入的节点值小于当前节点值,则将其插入当前节点的左子树中。
3. 如果要插入的节点值大于当前节点值,则将其插入当前节点的右子树中。
4. 重复以上步骤直到找到一个合适的位置插入节点。
2.2 删除节点在二叉树中删除节点也可以有多种方式,以下是在二叉搜索树中删除节点的过程: 1. 首先判断要删除的节点是否存在于二叉树中。
2. 如果该节点没有子节点,则直接删除该节点。
3. 如果该节点有一个子节点,则将其子节点替换为该节点。
4. 如果该节点有两个子节点,则找到该节点右子树的最小节点,将其值赋给要删除的节点,然后删除右子树的最小节点。
2.3 查找节点在二叉树中查找节点的方式与插入节点的方式相似: 1. 首先比较要查找的节点值与当前节点值大小关系。
2. 如果要查找的节点值小于当前节点值,则继续在当前节点的左子树中查找。
3. 如果要查找的节点值大于当前节点值,则继续在当前节点的右子树中查找。
4. 如果要查找的节点值等于当前节点的值,则找到了要查找的节点。
5. 如果在遍历完整个二叉树后仍然没有找到要查找的节点,则该节点不存在于二叉树中。
3. 二叉树的应用二叉树广泛应用于计算机科学领域,以下是几个常见的应用场景:3.1 搜索算法二叉树可以用于实现各种搜索算法,如二分查找法和哈夫曼编码算法。
3.2 数据库索引二叉树可以用于实现数据库索引结构,以提高数据的查找效率。
3.3 表达式树二叉树可以用于构建和求解数学表达式树,可以方便地进行计算。
二叉树及其应用实验报告
实验地点:一号教学楼微机室
实验名称:二叉树及其应用
实验目的:熟悉各种存储结构及应用二叉树解决具体问题
实验环境:微机室、DEV-C++
实验步骤:1、确定基本思路和设计思想
2、确定程序主题
3、进行编程设计
4、调试程序
5、分析程序错误,编译调试
6、总结经验
实验体会:二叉树的存储、遍历等非常多,但只要实际掌握了二叉树的原理,在课堂上认真听老师讲课,在编程时其实可以减少好多工作量。只要认真思考,参考一些案例,也可以调试好自己的程序。
void preorder_btree(b_tree root)
{
b_tree p=root;
if(p!=null)
{
printf("%3c",p->data);
preorder_btree(p->left);
preorder_btree(p->right);
}
}
/*中序遍历打印二叉排序树*/
void inorder_btree(b_tree root)
b_trБайду номын сангаасe p=root;
if(p!=null)
{
postorder_btree(p->left );
postorder_btree(p->right );
printf("%3c",p->data );
}
}
在调试程序的过程中,这几段关于二叉树遍历的原理其实老师都讲过,在调试程序的过程中,加深了对二叉树的遍历的理解,有助于更好地学习二叉树、应用二叉树。
{
b_tree p=root;
LAB06 二叉树的操作及应用
Lab06.二叉树的操作及应用【实验目的和要求】1.掌握二叉树顺序存储表示的实现及其基本操作;2.掌握线索二叉树类型的定义方法,会按对称序线索化二叉树和周游对称序线索二叉树;3.掌握优先队列的实现及其基本操作;4.掌握构造哈夫曼树的基本思想和哈夫曼树的数据结构设计,能编程实现哈夫曼树的构造;5.掌握哈夫曼树的基本应用——哈夫曼编码。
【实验内容】1.二叉树按顺序存储表示,编写一个C源程序,计算给定二叉树的叶结点数,并给出它的先根序列,或后根序列,或对称序列。
2.编写一个C源程序,对给定的二叉树,按对称序线索化该二叉树,并按对称序周游该对称序线索二叉树。
3. 编写一个C源程序,恰当定义优先队列,并对给定的优先队列,实现插入和删除最小结点的操作。
4.简述构造哈夫曼树的基本思想和哈夫曼树的数据结构设计,并编程实现哈夫曼树的构造。
5.简述哈夫曼编码的原理和方法,编程实现哈夫曼编码与解码。
【实验仪器与软件】1.CPU主频在1GHz以上,内存在512Mb以上的PC;2.VC6.0,Word 2003及以上版本。
实验讲评:实验成绩:评阅教师:2012 年月日Lab06.二叉树的操作及应用一、顺序存储表示二叉树及其基本运算其顺序表示为:首先要对它进行扩充,增加一些并不存在的空结点,使之成为一棵完全二叉树,然后再用一维数组顺序存储。
其存储表示为:s t r u c t S e q B i n T r e e{/*顺序二叉树类型定义*/i n t M A X N U M/*完全二叉树中允许结点的最大个数*/i n t n;/*改造成完全二叉树后,结点的实际个数*/D a t a T y p e*n o d e l i s t;/*存放结点的数组*/};t y p e d e f s t r u c t S e q B i n T r e e*P S e q B i n T r e e;二、对称序线索化该二叉树及其周游的实现要按对称序周游对称序线索二叉树,首先找到对称序列中的第一个结点,然后依次找到结点的后继结点,直至其后继结点为空即可。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验6:二叉树及其应用一、实验目的树是数据结构中应用极为广泛的非线性结构,本单元的实验达到熟悉二叉树的存储结构的 特性,以及如何应用树结构解决具体问题。
二、问题描述首先,掌握二叉树的各种存储结构和熟悉对二叉树的基本操作。
其次,以二叉树表示算术表达 式的基础上,设计一个十进制的四则运算的计算器。
三、实验要求1、 如果利用完全二叉树的性质和二叉链表结构建立一棵二叉树,分别计算a) 统计叶子结点的个数。
b)求二叉树的深度。
2、 十进制的四则运算的计算器可以接收用户来自键盘的输入。
3、 由输入的表达式字符串动态生成算术表达式所对应的二叉树。
4、 自动完成求值运算和输出结果。
四、实验环境PC 微机DOS 操作系统或Windows 操作系统 Turbo C 程序集成环境或 Visual C++程序集成环境五、实验步骤1、 根据二叉树的各种存储结构建立二叉树;2、 设计求叶子结点个数算法和树的深度算法;3、 根据表达式建立相应的二叉树,生成表达式树的模块;如算术表达式:a+b*(c-d)-e/f+/aebCd5、程序运行效果,测试数据分析算法。
六、功能分析4、根据表达式树,求出表达式值,生成求值模块;存储结构typedef union{int Operator; // 操作符float Opera nd; // 操作数}ln t_Float;//表达式树typedef struct Bin aryTreeNode{In t_Float Data; // 数据域int IsOperator; // 判断是不是操作数的标志位struct Bi naryTreeNode *RChild;〃左子树struct Bi naryTreeNode *LChild;〃右子树}BiTreeNode, *lpBiTreeNode;//栈的定义typedef struct {lpBiTreeNode *base;lpBiTreeNode *top;int stacksize;}SqStack;函数一览表lpBiTreeNode GetTop( SqStack s );// 取栈顶结点函数int lsEmpty( SqStack s );// 判空函数int In itStack( SqStack &s );// 初始化栈函数int Pop( SqStack & s, lpBiTreeNode &e );// 出栈函数int Push( SqStack & s, lpBiTreeNode e );// 入栈函数int ln( int c, int* op );// 判断c 是否在op 中int Precede( int thetal, i nt theta2 );// 比较运算符号的优先级int isNum( int c );// 判断是不是数int Getl nput(l nt_Float *Result);// 读入输入的数lpBiTreeNode CreateBiTree();// 创建二叉树bool calculate(lpBiTreeNode Root, float *result);// 计算二叉树化表达式的值in t getLeafNum(lpBiTreeNode Root);// 计算二叉树的叶子结点数in t getDepth(lpBiTreeNode Root);// 计算二叉树的深度递归,核心在于num=nu mleft+ nu mright递归,核心在于depth=max(leftdepth,righydepth)+1Int num(二叉树*p){If (空树)return 0 ;Else if (一个节点的树)return 1 ;Else{Return num (num (左子树)+num (右子树));}}Int depth(二叉树*p){If (空树)return 0 ;Else if (一个节点的树)return 1 ;Else{;Retur nmax (depth (左子树),depth (右子树)+1);}}七、程序代码#i nclude <stdio.h>#i nclude <malloc.h>#defi ne STACK_INIT_SIZE 100#defi ne STACKINCREMENT 10#defi ne ERROR 0#defi ne NUMBER 1#defi ne SIMBLE 2int OP[8] = { '+', '-', '*', '/', '(', ')', '#', 0 };////共用体typedef union{int Operator; // 操作符float Opera nd; // 操作数}In t_Float;//表达式树typedef struct Bin aryTreeNode{In t_Float Data; // 数据域运算符数组int IsOperator; // 判断是不是操作数的标志位struct Bin aryTreeNode *RChild;〃左子树struct Bin aryTreeNode *LChild;〃右子树}BiTreeNode, *lpBiTreeNode;//栈的定义typedef struct {lpBiTreeNode *base;lpBiTreeNode *top;int stacksize;}SqStack;//函数声明区lpBiTreeNode GetTop( SqStack s );// 取栈顶结点函数int lsEmpty( SqStack s );// 判空函数int Ini tStack( SqStack &s );// 初始化栈函数int Pop( SqStack & s, lpBiTreeNode &e );// 出栈函数int Push( SqStack & s, lpBiTreeNode e );// 入栈函数int In( int c, int* op );// 判断c 是否在op 中int Precede( int theta1, i nt theta2 );// 比较运算符号的优先级int isNum( int c );// 判断是不是数int GetI nput(l nt_Float *Result);// 读入输入的数lpBiTreeNode CreateBiTree();// 创建二叉树bool calculate (l pBiTreeNode Root, float *result);// 计算二叉树化表达式的值in t getLeafNu m(l pBiTreeNode Root);// 计算二叉树的叶子结点数in t getDepth (l pBiTreeNode Root);// 计算二叉树的深度int mai n() //主函数{lpBiTreeNode Root;// 二叉树float result; //表达式运算结果if( Root = CreateBiTree() )// 若创建二叉树失败则不会执行if操作{printf(" 二叉树叶子数=%d\n", getLeafNum(Root));printf(" 二叉树的深度=%d\n", getDepth(Root));if( calculate(Root, & result) )// 计算结果{printf(" 表达式的值=%0.2f\n", result);prin tf("INPUT ERROR'n");return 0;IpBiTreeNode GetTop( SqStack s ) {lpBiTreeNode e;if( s.top == s.base )//栈为空情况return NULL;e = *(s.top -1);//top 指针指向栈顶兀素的后一个空间} return e;int IsEmpty( SqStack s ) {if( s.top == s.base )//栈为空return 1; elsereturn 0;}int Ini tStack( SqStack &s ) {s.base = (IpBiTreeNode *)malloc( STACK_INIT_SIZE*sizeof(lpBiTreeNode)栈基址空间if(!s.base)〃 分配空间失败return 0;s.top = s.base;// 栈顶指针s.stacksize = STACK_INIT_SIZE;〃 初始化栈大小return 1;} int Pop( SqStack &s, lpBiTreeNode &e )else printf("ERROR");} elseprintf (”********************************\n"); );//mallocif( s.top == s.base )// return 0;s.top --;//top 指针前移 e = *s.top;〃 取栈顶元素 return 1; }return 0;s.top = s.base + s.stacksize;// 栈顶指针位置 s.stacksize += STACKINCREMENT;// 新栈的大小}*s.top = e;// 元素 e 入栈 s.top ++;// 栈顶指针后移 return 1;int In( int c, int* op ) // 判断c 是否在op 中,op 为以结尾的数组{while( *op != 0 )// 比较所有元素,最后一个为{if( c == *op )// 相等,存在 return 1return 1; op ++;//op 指针后移 } return 0;int Precede( int theta1, i nt theta2 )// {int i, j;int op_look[7][7]=II, , , , , , J 5{'>''>''—>''>' }I, , , , , , J 5 {'>''>''>''>''<''>''>' }I, , , , , ,J 5{'>''>''>''>''<''>''>' }空栈int Push( SqStack & s, IpBiTreeNode e )// {if( s.top - s.base >= s.stacksize )// {s.base = (lpBiTreeNodeSTACKINCREMENT)*sizeof(lpBiTreeNode) );//if(!s.base)入栈函数空间已满 *)realloc(s.base, (s.stacksize +重新分配空间比较优先级I ,,,,,,J 5{ '<' '<' '<' '<' '<' ' = ' ' ' }I , 5 5 5 5 5 J 5{'>''>''>''>'' ''>''>' }I 5 5 5 5 5 5 J 5{ '<' '<' '<' '<' '<' ' ' ' = ' }};〃运算符优先级二维数组switch( thetal )// 定位thetal { case '+':i = 0;break;case '-':i = 1;break;case '*':i = 2;break;case '/':i = 3;break;case '(':i = 4;break;case ')':i = 5;break;case '#':i = 6;break;default:return 0;}switch( theta2 )//定位theta2 {case '+':j = 0; break;case '-':j = 1; break;j = 2; break; case '/':j = 3;break; case '(': j = 4; break; case ')': j = 5; break; case '#':j = 6; break; default:return 0;}return op_look[i][j];〃 }int isNum( int c )// 是不是数字 {if( c >= 'O' && c <= 9 )//ascii码return 1; else return 0;}int c;In t_Float result; int IsNumber = 0; // int IsFloat = 0; // int i,t=1;int GetI nput(l nt_Float *Result) // {static int buffer = 0; // 返回值:无,1数字,2符号缓存存储数字后的符号判断优先级是否为数字 是否为小数result.Opera nd = 0;if(ln( buffer, OP)) II缓存中有符号{result.Operator = buffer;buffer = 0;Result->Operator = result.Operator;return SIMBLE; II 符号}II 去前导空格c = getchar();while ( c == ' ' && c != 10 ){c = getchar();}while( c != ' ' && c != 10 ) II 不是空格和回车{if(isNum(c)) II 是数字{IsNumber = 1;c = c - 48; II 字符到整型if(IsFloat == 0)result.Opera nd = result.Opera nd*10 + c; else{result.Opera nd = result.Opera nd*10 + c; IsFloat++;}}else if(c =='.'){if(IsFloat != 0) II 两个小数点{Result->Opera nd = 0;return ERROR;}elseIsFloat = 1;}else if (In(c, OP)){}if(lsNumber) // 数字后接符号{if(lsFloat == 1){Result->Opera nd = 0;return ERROR;}else{buffer = c;for(i=0; i<lsFloat-1; i++)t*=10;Result->Opera nd = result.Opera nd/(float)t; return NUMBER; // 数字}}else{Result->Operator = c;return SIMBLE; // 符号}}c = getchar();}buffer = 0;if(IsNumber)// 处理数字{if(IsFloat == 1){Result->Opera nd = 0;return ERROR;}else{for(i=0; i<IsFloat-1; i++)t*=10;Result->Opera nd = result.Opera nd/(float)t;return NUMBER;}else if(result.Opera nd == 0)// {Result->Opera nd = 0; return ERROR; }else//处理符号 {Result->Operator = result.Operator; return SIMBLE; } }pNode = (l pBiTreeNode)malloc(sizeof(BiTreeNode)); pNode->Data.Operator = '#'; pNode->IsOperator = 1; pNode->LChild = NULL; pNode->RChild = NULL; Push( Operator, pNode );while( !( r == SIMBLE && c.Operator == '#') || GetTop(Operator)->Data.Operator# )// 处理到#{if(r == ERROR)return NULL; if( r == NUMBER ) // 是数字错误输入lpBiTreeNode CreateBiTree()〃 {SqStack Opera nd; // SqStack Operator; // lpBiTreeNode pNode; lpBiTreeNode theta,a,b; In t_Float c; printf("创建新的二叉树操作数 操作符******************************请输入一个算式并以prin tf("QAQ int r = GetI nput(&c); In itStack(Operand);//In**\n");'#'号结尾:\n")初始化操作数栈 初始化操作符栈!={}pNode = (I pBiTreeNode)malloc(sizeof(BiTreeNode)); pNode->Data.Opera nd =c.Opera nd;pNode->lsOperator = 0;pNode->LChild = NULL;pNode->RChild = NULL;Push(Opera nd,pNode);r = GetI nput(&c);}else if( r == SIMBLE ) // 是符号{switch( Precede(GetTop(Operator)->Data.Operator, c.Operator)){case '<': II栈顶元素优先权低pNode = (l pBiTreeNode)malloc(sizeof(BiTreeNode));pNode->Data.Operator = c.Operator;pNode->IsOperator = 1;pNode->LChild = NULL; pNode->RChild = NULL; Push( Operator, pNode );r = Getl nput (&c);break;case '=': II '(',')' 相遇,脱括号Pop( Operator, pNode );r = Getl nput (&c);break;case '>': II 栈顶元素优先权高,退栈并将运算结果入栈Pop( Operator, theta );Pop( Opera nd, b);Pop( Opera nd, a);theta->LChild = a;theta->RChild = b;Push(Operand, theta);break;}}}retur n GetTop(Opera nd);bool calculate (l pBiTreeNode Root, float *result)〃 { float resultLchild; float resultRchild; if( Root != NULL )// {if(Root->LChild == NULL && Root->RChild == NULL)// {非空*result = Root->Data.Opera nd; return true;计算二叉树的值叶子节点}else if(Root->LChild == NULL || Root->RChild == NULL)//return false;else//左右子树都存在的情况,递归计算 {switch (Root->Data.Operator)〃 {case '+':不可能出现单子树情况取操作符if( calculate(Root->LChild, & resultLchild)==false )return false;if( calculate(Root->RChild, &resultRchild)==false ) return false; *result = resultLchild + resultRchild;值加上右子树的值 break;case '-': // 该二叉树的值等于左子树的值减去右子树的值 if( calculate(Root->LChild, &resultLchild)==false ) return false; if( calculate(Root->RChild, & resultRchild)==false ) return false;*result = resultLchild - resultRchild; // 该二叉树的值等于左子树的break; case '*': if( calculate(Root->LChild, &resultLchild)==false )return false;if( calculate(Root->RChild, &resultRchild)==false )return false;*result = resultLchild * resultRchild;树的值乘上右子树的值//该二叉树的值等于左子break; case '/':if( calculate(Root->LChild, & resultLchild)==false )return false;if( calculate(Root->RChild, &resultRchild)==false ) return false; *result = resultLchild / resultRchild;树除以加上右子树的值break; } } }return true; }in t getLeafNu m(l pBiTreeNode Root)// { int LeafnumLchild;// int LeafnumRchild;// if( Root != NULL )// {if(Root->LChild == NULL && Root->RChild == NULL)计算叶子节点数左子树的叶子结点数 右左子树的叶子结点数 非空//该结点是叶子节点return 1;else {LeafnumLchild = getLeafNum(Root->LChild);〃 LeafnumRchild =getLeafNum(Root->RChild);〃 return LeafnumLchild + LeafnumRchild;// 递归计算左子树的 num 递归计算右子树的num 总的叶子节点数等于左子树的加上右子树的 } } return 0; } in t getDepth (l pBiTreeNode Root)// { int LeafDepthL;// int LeafDepthR;// if( Root !=NULL )//计算二叉树的深度 左子树的深度右子树的深度 非空//该二叉树的值等于左子{if(Root->LChild == NULL && Root->RChild == NULL)return 1; else {LeafDepthL = getDepth(Root->LChild);〃 左子树的深度 LeafDepthR = getDepth(Root->RChild);〃右子树的深度return 1 + (LeafDepthL>LeafDepthR?LeafDepthL:LeafDepthR);〃 左、右子树的最大深度加上1} }return 0; }六、测试数据1、输入数据:2.2* ( 3.1 + 1.20)-7.5/3正确结果:6.96CAUsers\apple-pc\Deskto p\zh r_test.exe帳输人一个算貢:K.2*(3.1+1.20>-7.5/3#I Process e K it G d after 26昏 香 wivh rctwrn请按任意键纟廉续・・・2、输入数据:(1+2)*3+(5+6*7);正确输出:56C :\UsersV ppi e-pc \Deskto p\zhr_te st.exe//叶子结点实际深度等于Bi-4 6 ■兀八、实验总结在实现int getDepth(IpBiTreeNode Root)// 计算二叉树的深度、int getLeafNum(lpBiTreeNode Root)//计算叶子节点数函数时,都用到了递归的思想。