实验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、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 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)//计算叶子节点数函数时,都用到了递归的思想。