遍历算法及应用

合集下载

深度优先遍历例题

深度优先遍历例题

深度优先遍历例题摘要:一、深度优先遍历概念介绍1.定义2.特点二、深度优先遍历算法应用1.图形遍历2.搜索算法三、深度优先遍历例题解析1.题目一:二叉树的深度优先遍历1.分析2.算法实现3.答案解析2.题目二:链式广度优先遍历1.分析2.算法实现3.答案解析四、深度优先遍历实战技巧与优化1.避免回溯2.提高效率正文:一、深度优先遍历概念介绍1.定义深度优先遍历(Depth-First Traversal,简称DFT)是一种遍历树或图的算法。

它沿着一个路径一直向前,直到达到最深的节点,然后回溯到上一个节点,继续沿着另一个路径遍历。

2.特点深度优先遍历的特点是访问一个节点后,会沿着该节点的子节点继续遍历,直到没有未访问的子节点为止。

此时,遍历过程会回溯到上一个节点,继续访问其未访问的子节点。

二、深度优先遍历算法应用1.图形遍历深度优先遍历在图形处理领域有广泛应用,如图像处理中的边缘检测、图像分割等。

通过遍历图像像素点,可以发现像素点之间的关系,从而实现图像处理任务。

2.搜索算法深度优先搜索(DFS)是一种经典的搜索算法,它采用深度优先策略在树或图中寻找目标节点。

DFS算法常用于解决迷宫问题、八皇后问题等。

三、深度优先遍历例题解析1.题目一:二叉树的深度优先遍历1.分析二叉树的深度优先遍历通常采用递归或栈实现。

递归方法简单,但效率较低;栈方法效率较高,但实现较复杂。

2.算法实现(递归)```def dfs(root):if not root:returnprint(root.val, end=" ")dfs(root.left)dfs(root.right)```3.答案解析按照题目给定的二叉树,进行深度优先遍历,得到的序列为:1 2 4 5 3 6 8。

2.题目二:链式广度优先遍历1.分析链式广度优先遍历与树的同层遍历类似,采用队列实现。

队列中的元素依次为当前层的节点,每次遍历时,取出队首节点,将其相邻节点加入队列,并将其标记为已访问。

数据结构中的图的遍历算法

数据结构中的图的遍历算法

数据结构中的图的遍历算法图是一种非常重要且广泛应用的数据结构,它由顶点和边组成,可以用来表示各种实际问题,如社交网络、路线规划等。

图的遍历算法是对图中的所有顶点进行系统访问的方法,它可以用来查找、遍历和搜索图中的元素。

本文将介绍图的遍历算法的基本概念和常用的实现方法。

一、图的遍历算法概述图的遍历算法是指按照某种规则遍历图中的所有顶点,以便于查找、遍历和搜索图中的元素。

常用的图的遍历算法有深度优先搜索(DFS)和广度优先搜索(BFS)两种。

深度优先搜索(DFS)是一种先访问顶点的所有邻接顶点,再递归访问邻接顶点的邻接顶点的算法。

它以深度为优先级,一直向前走到不能继续为止,然后返回到前一个结点,继续向前走,直到遍历完整个图。

广度优先搜索(BFS)是一种先访问顶点的所有邻接顶点,再访问邻接顶点的邻接顶点,以此类推的算法。

它以广度为优先级,先访问离起始顶点最近的顶点,然后依次访问离起始顶点更远的顶点,直到遍历完整个图。

二、深度优先搜索(DFS)深度优先搜索是一种递归的搜索算法,它的基本思想是从图的某个顶点出发,沿着一条路径一直深入直到不能继续为止,然后返回到前一个结点,继续向前走。

具体实现时,可以使用递归或栈来保存需要访问的顶点。

以下是深度优先搜索的基本步骤:1. 选择一个起始顶点作为当前顶点,将其标记为已访问。

2. 访问当前顶点,并将其加入遍历结果。

3. 从当前顶点的未访问邻接顶点中选择一个作为下一个当前顶点,重复步骤2。

4. 如果当前顶点的所有邻接顶点都已访问,则返回到前一个顶点,重复步骤3。

5. 重复步骤4,直到遍历完整个图。

三、广度优先搜索(BFS)广度优先搜索是一种迭代的搜索算法,它的基本思想是从图的某个顶点出发,依次访问其所有未访问过的邻接顶点,然后再依次访问这些邻接顶点的未访问过的邻接顶点,直到遍历完整个图。

具体实现时,可以使用队列来保存需要访问的顶点。

以下是广度优先搜索的基本步骤:1. 选择一个起始顶点作为当前顶点,将其标记为已访问,并将其加入遍历结果。

二叉树遍历算法的应用

二叉树遍历算法的应用

二叉树遍历算法的应用二叉树是一种常用的数据结构,它由节点和节点之间的链接组成。

每个节点最多有两个子节点,分别称为左子节点和右子节点。

二叉树遍历算法是指按照一定的顺序访问二叉树中的所有节点,经典的二叉树遍历算法有前序遍历、中序遍历和后序遍历。

这些遍历算法在计算机科学中有广泛的应用。

一、前序遍历前序遍历算法的访问顺序是先访问根节点,然后依次访问左子树和右子树。

在实际应用中,前序遍历算法十分常见,具有以下几个应用:1.树的复制:如果需要复制一棵二叉树,可以使用前序遍历算法遍历原树,然后按照递归或迭代的方式创建新节点,并复制原节点的值。

2.表达式求值:对于一个二叉树表示的数学表达式,前序遍历算法可以用来计算表达式的值。

遍历到运算符节点时,先计算左子表达式的值,然后计算右子表达式的值,最后根据运算符进行计算。

3.文件系统遍历:文件系统可以被视为一个树状结构,前序遍历算法可以按照前序的顺序遍历文件系统中的所有文件和文件夹。

二、中序遍历中序遍历算法的访问顺序是先访问左子树,然后访问根节点,最后访问右子树。

中序遍历算法也有多个应用:1.二叉树的中序遍历得到的节点值是按照从小到大的顺序排列的。

因此,可以使用中序遍历算法验证一个二叉树是否为二叉树。

2.二叉树中序遍历的结果可以用来实现按照升序排列的有序集合的功能。

例如,在数据库中存储的数据可以通过中序遍历的结果进行排序。

3.中序遍历算法可以将一个二叉树转换为一个有序的双向链表。

在遍历过程中,维护一个前驱节点和一个后继节点,并进行链接操作。

三、后序遍历后序遍历算法的访问顺序是先访问左子树,然后访问右子树,最后访问根节点。

后序遍历算法也有多个应用:1.后序遍历算法可以用来计算二叉树的深度。

在遍历过程中,可以维护一个全局变量来记录最大深度。

2.后序遍历算法可以用来判断一个二叉树是否为平衡二叉树。

在遍历过程中,可以比较左右子树的高度差,判断是否满足平衡二叉树的定义。

3.后序遍历算法可以用来释放二叉树的内存。

数据结构实验报告图的遍历讲解

数据结构实验报告图的遍历讲解

数据结构实验报告图的遍历讲解一、引言在数据结构实验中,图的遍历是一个重要的主题。

图是由顶点集合和边集合组成的一种数据结构,常用于描述网络、社交关系等复杂关系。

图的遍历是指按照一定的规则,挨次访问图中的所有顶点,以及与之相关联的边的过程。

本文将详细讲解图的遍历算法及其应用。

二、图的遍历算法1. 深度优先搜索(DFS)深度优先搜索是一种常用的图遍历算法,其基本思想是从一个顶点出发,沿着一条路径向来向下访问,直到无法继续为止,然后回溯到前一个顶点,再选择此外一条路径继续访问。

具体步骤如下:(1)选择一个起始顶点v,将其标记为已访问。

(2)从v出发,选择一个未被访问的邻接顶点w,将w标记为已访问,并将w入栈。

(3)如果不存在未被访问的邻接顶点,则出栈一个顶点,继续访问其它未被访问的邻接顶点。

(4)重复步骤(2)和(3),直到栈为空。

2. 广度优先搜索(BFS)广度优先搜索是另一种常用的图遍历算法,其基本思想是从一个顶点出发,挨次访问其所有邻接顶点,然后再挨次访问邻接顶点的邻接顶点,以此类推,直到访问完所有顶点。

具体步骤如下:(1)选择一个起始顶点v,将其标记为已访问,并将v入队。

(2)从队首取出一个顶点w,访问w的所有未被访问的邻接顶点,并将这些顶点标记为已访问,并将它们入队。

(3)重复步骤(2),直到队列为空。

三、图的遍历应用图的遍历算法在实际应用中有广泛的应用,下面介绍两个典型的应用场景。

1. 连通分量连通分量是指图中的一个子图,其中的任意两个顶点都是连通的,即存在一条路径可以从一个顶点到达另一个顶点。

图的遍历算法可以用来求解连通分量的个数及其具体的顶点集合。

具体步骤如下:(1)对图中的每一个顶点进行遍历,如果该顶点未被访问,则从该顶点开始进行深度优先搜索或者广度优先搜索,将访问到的顶点标记为已访问。

(2)重复步骤(1),直到所有顶点都被访问。

2. 最短路径最短路径是指图中两个顶点之间的最短路径,可以用图的遍历算法来求解。

图的遍历 实验报告

图的遍历  实验报告

图的遍历实验报告一、引言图是一种非线性的数据结构,由一组节点(顶点)和节点之间的连线(边)组成。

图的遍历是指按照某种规则依次访问图中的每个节点,以便获取或处理节点中的信息。

图的遍历在计算机科学领域中有着广泛的应用,例如在社交网络中寻找关系紧密的人员,或者在地图中搜索最短路径等。

本实验旨在通过实际操作,掌握图的遍历算法。

在本实验中,我们将实现两种常见的图的遍历算法:深度优先搜索(DFS)和广度优先搜索(BFS),并比较它们的差异和适用场景。

二、实验目的1. 理解和掌握图的遍历算法的原理与实现;2. 比较深度优先搜索和广度优先搜索的差异;3. 掌握图的遍历算法在实际问题中的应用。

三、实验步骤实验材料1. 计算机;2. 编程环境(例如Python、Java等);3. 支持图操作的相关库(如NetworkX)。

实验流程1. 初始化图数据结构,创建节点和边;2. 实现深度优先搜索算法;3. 实现广度优先搜索算法;4. 比较两种算法的时间复杂度和空间复杂度;5. 比较两种算法的遍历顺序和适用场景;6. 在一个具体问题中应用图的遍历算法。

四、实验结果1. 深度优先搜索(DFS)深度优先搜索是一种通过探索图的深度来遍历节点的算法。

具体实现时,我们可以使用递归或栈来实现深度优先搜索。

算法的基本思想是从起始节点开始,选择一个相邻节点进行探索,直到达到最深的节点为止,然后返回上一个节点,再继续探索其他未被访问的节点。

2. 广度优先搜索(BFS)广度优先搜索是一种逐层遍历节点的算法。

具体实现时,我们可以使用队列来实现广度优先搜索。

算法的基本思想是从起始节点开始,依次遍历当前节点的所有相邻节点,并将这些相邻节点加入队列中,然后再依次遍历队列中的节点,直到队列为空。

3. 时间复杂度和空间复杂度深度优先搜索和广度优先搜索的时间复杂度和空间复杂度如下表所示:算法时间复杂度空间复杂度深度优先搜索O(V+E) O(V)广度优先搜索O(V+E) O(V)其中,V表示节点的数量,E表示边的数量。

matlab遍历算法

matlab遍历算法

matlab遍历算法【最新版】目录1.MATLAB 简介2.遍历算法的概念3.MATLAB 中的遍历算法实现4.遍历算法的实际应用5.总结正文1.MATLAB 简介MATLAB 是一种广泛应用于科学计算、数据分析、可视化等领域的编程语言。

它具有强大的矩阵计算能力,丰富的函数库和简洁的语法结构,使得用户可以更加高效地完成各种计算任务。

2.遍历算法的概念遍历算法是一种用于访问或处理数据集合的算法。

它通常用于遍历数据集合中的所有元素,以便对这些元素进行特定的操作。

遍历算法可以分为不同类型,例如顺序遍历、随机遍历和二进制遍历等。

3.MATLAB 中的遍历算法实现在 MATLAB 中,遍历算法可以通过循环结构(如 for 循环、while 循环等)来实现。

此外,MATLAB 还提供了一些内置函数,如 ismember、isequal 和 find 等,这些函数可以方便地用于遍历数据集合。

下面是一个简单的示例,展示了如何在 MATLAB 中使用 for 循环实现遍历算法:```matlab% 创建一个数组arr = [1, 2, 3, 4, 5];% 使用 for 循环遍历数组for i = 1:length(arr)disp(arr(i));end```4.遍历算法的实际应用遍历算法在实际应用中有很多用途,例如数据分析、图像处理和网络爬虫等。

在 MATLAB 中,遍历算法可以用于处理大量的数据,以完成各种复杂的计算任务。

例如,在图像处理中,遍历算法可以用于遍历图像中的所有像素,以便对每个像素进行特定的操作,如调整亮度、对比度等。

5.总结MATLAB 是一种强大的编程语言,可以方便地实现遍历算法。

通过使用循环结构和内置函数,用户可以高效地遍历数据集合,完成各种复杂的计算任务。

二叉树的遍历算法实验报告

二叉树的遍历算法实验报告

二叉树的遍历算法实验报告二叉树的遍历算法实验报告引言:二叉树是计算机科学中常用的数据结构之一,它是由节点组成的层次结构,每个节点最多有两个子节点。

在实际应用中,对二叉树进行遍历是一项重要的操作,可以帮助我们理解树的结构和节点之间的关系。

本文将介绍二叉树的三种遍历算法:前序遍历、中序遍历和后序遍历,并通过实验验证其正确性和效率。

一、前序遍历前序遍历是指先访问根节点,然后按照先左后右的顺序遍历左右子树。

具体的实现可以通过递归或者使用栈来实现。

我们以递归方式实现前序遍历算法,并进行实验验证。

实验步骤:1. 创建一个二叉树,并手动构造一些节点和它们之间的关系。

2. 实现前序遍历算法的递归函数,函数的输入为根节点。

3. 在递归函数中,首先访问当前节点,然后递归调用函数遍历左子树,最后递归调用函数遍历右子树。

4. 调用前序遍历函数,输出遍历结果。

实验结果:经过实验,我们得到了正确的前序遍历结果。

这证明了前序遍历算法的正确性。

二、中序遍历中序遍历是指按照先左后根再右的顺序遍历二叉树。

同样,我们可以使用递归或者栈来实现中序遍历算法。

在本实验中,我们选择使用递归方式来实现。

实验步骤:1. 继续使用前面创建的二叉树。

2. 实现中序遍历算法的递归函数,函数的输入为根节点。

3. 在递归函数中,首先递归调用函数遍历左子树,然后访问当前节点,最后递归调用函数遍历右子树。

4. 调用中序遍历函数,输出遍历结果。

实验结果:通过实验,我们得到了正确的中序遍历结果。

这证明了中序遍历算法的正确性。

三、后序遍历后序遍历是指按照先左后右再根的顺序遍历二叉树。

同样,我们可以使用递归或者栈来实现后序遍历算法。

在本实验中,我们选择使用递归方式来实现。

实验步骤:1. 继续使用前面创建的二叉树。

2. 实现后序遍历算法的递归函数,函数的输入为根节点。

3. 在递归函数中,首先递归调用函数遍历左子树,然后递归调用函数遍历右子树,最后访问当前节点。

4. 调用后序遍历函数,输出遍历结果。

数据结构课程设计二 叉 树 遍 历 及 应 用

数据结构课程设计二 叉 树 遍 历 及 应 用

实验报告课程:数据结构课程设计设计题目:二叉树遍历及应用学号:班级:软件11k1姓名: 南方小羊指导教师:刘军二叉树的遍历1、问题描述利用先序遍历建立一棵二叉树,并分别用前序、中序、后序遍历该二叉树2、节点形式Lchild data Rchild3、说明(1)输入数据:1,2,3,0,0,4,0,0,5,0,0其中“0”表示空子树。

(2)输出数据:先序:1,2,3,4,5中序:3,2,4,1,5后序:3,4,2,5,1二叉树的应用1、问题描述运用二叉树的遍历的算法,编写算法分别实现如下功能。

(1)求出二叉树中的结点的总数。

(2)求出二叉树中的叶子数目。

(3)求出二叉树的深度。

运用上题所建立的二叉树,求出其结点总数、叶子数目、深度,最后释放所有结点。

二叉树结点结构中包数据域(data),指针域(*lchild,*rchild)。

结点结构的代码如下:typedef struct tree{int data;struct tree *lchild,*rchild;}*bitree;本实例使用的是二叉树,首先建立头结点,并且保存数据,然后根据递归方法,分别建立其左右孩子结点,且左右孩子结点的指针域指向空。

先序递归遍历时,输出第一个根结点数据,然后分别遍历左子树再遍历右子树,中序遍历,先访问根结点的左子树输出数据,再输出根结点的数据,再访问右子树,后序遍历先访问根结点的右子树,再访问根结点,再访问左子树输出。

统计二叉树叶子的个数可以看成一个遍历问题,访问一个结点,判断该结点是否为叶子,如果是将叶子树加1,可以采用任何遍历实现,求二叉树的深度是假设根结点为第一层的结点,所有K层结点的左右孩子在K+1层,所以可以通过先序遍历计算二叉树中每个结点的层数,其中最大的就是二叉树的深度。

四、实验心得:树结构是数据结构课程的典型内容,而且综合使用了多种逻辑结构,具有代表性,可以锻炼个人编程能力。

在刚开始选题后,我感觉无从下手,一是因为没有实践经验,二是因为对数据结构课程的内容没有把握到位,然后在参考一些专业书籍并且学习了之前其他人的课程设计,才逐渐可以上手去自己做。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验报告课程名称算法与数据结构姓名何劼专业计算机科学与技术部别指导教员日期年月日实验项目列表实验报告姓名:何劼学号:专业:计算机科学与技术部别:实验地点:实验时间: 2012、4、17 设备编号:同组人员:指导教员签字:成绩:教员评语:一、实验名称遍历算法及应用二、实验目的1 .掌握二叉树的递归构造方法2 .掌握二叉树的递归遍历方法3 .掌握二叉树的递归遍历的简单应用三、实验内容和要求编写完成如下功能的程序。

1 .构造二叉树(中序加后序序列造树选做)2 .删除树中原来所有1 度的结点3 .求给定的任意结点的父亲4 .从根到叶的一条最长路经5 .计算树中叶结点数(选)6 .判定一棵树是否是正则树(选)7 .按层遍历树,并输出树宽(选)要求:1 .先构造出二叉树,然后输出原树的三种遍历序列。

2 .在删除原来所有1 度的结点后,再输出新二叉树的三种遍历序列。

3 .直接输出给定结点的父结点的值。

4 .输出这条最长的路径。

5 .输出树中叶结点的数目。

6 .输出一棵树是否是正则树的判定结论。

7 .按层遍历树,并输出树宽四、实验环境1.硬件环境:PC机2.软件环境:Windows操作系统,VC++集成开发环境五、算法设计思想题目一—构造二叉树。

为了使得程序能够更加具有通用性,设计者在构造二叉树时编写了三种造树方式,分别是先序扩充序列造树,先序加中序序列造树以及中序加后序造树。

其中前两个程序已经在课上得到了实现。

中序加后序造树,主要问题就是左右子树上下标界的确定,运用图示法能够较为形象准确的解决此问题。

三种序列的输出这里不加赘述。

题目二——删除树中1度结点。

采用先序遍历递归。

首先判断下一结点是否为1度结点,若为1度结点并且有右儿子,返回1;若为1度结点并且有左儿子,返回2;不为1度结点返回0。

再根据返回值的情况进行勾连和结点的删除。

题目三——求结点的父亲。

采用后续遍历递归。

设计者配合使用了类似于“红绿灯”的found 标记值。

若为0则还未发现结点;若为1则找到该结点返回上一层输出其父亲,并置found为2。

题目四——输出从根到叶的一条最长路径。

首先找到最长路径对应的叶子(先序),再求取叶子的祖先(后序)。

运用order数组存储其祖先,最后从后到前输出。

这样得到的路径是符合从根到叶的顺序的。

题目五——计算叶子的数目。

采用先序遍历递归。

判断是否为叶子。

若为叶节点num加1;反之递归判断其左儿子,右儿子。

题目六——判断正则树。

如果存在这样一个结点,它只有一个儿子,那么found标记值置1。

当递归遍历完整棵树之后,found等于1则不为正则树;反之则为正则树。

题目七——按层遍历树。

运用了队的结构。

初始时刻last指针boundary指针重合,first 指针在两者之前1位。

树根先入队,并访问它,first指针后移,与boundary指针重合,说明该层遍历完成,breadth记录该层宽度。

然后其左儿子,右儿子入队,last指针移至队尾。

接着访问下一结点……每当first与boundary重合则说明该层遍历完成。

六、主要问题与解决方法构造二叉树时,主要是中序加后序造树的递归标界的确定。

如上文所说,运用图示法比较形象准确的解决了问题。

删除1度结点时,设计者一开始觉得问题较为简单,但是真正上手之后,发现还是有一定难度的,不仅需要判断采用哪种遍历方式,还需要考虑找到一度结点输出最长路径时,一开始递归输出叶子祖先的顺序是从叶子到根。

后来运用一个数组,将顺序倒了过来。

按层遍历树时,按照教员的提示,运用队结构和boundary指针的方式,实现了按层遍历。

并且记录了树宽。

这个思想值得学习。

七、实验结果程序对题目要求的构造二叉树、删除树中1度结点、输出从根到叶的一条最长路径、求结点的父亲、计算叶子的数目和判断正则树的问题进行了解决。

在构造二叉树的问题中加入了先序扩充序列造树和中序加后序造树。

在最后还添加了教员课上要求的按层遍历树以及求树宽的代码。

经测试,该程序是可以解决以上问题的。

而对于整个程序,稍微不太满意的地方是对于1度结点的删除和求最长路径的函数部分。

两者过于冗长,并且进行了函数的二次调用。

对于前者,经过教员后期课上指导发现可以有更好的较为简单的解决方法(主要思想是运用引用型参数),而后者暂时还没有找到较好的方法能够只对树一次遍历就得到从根到叶的顺序输出。

以下是程序运行的截图和部分程序运行示意图:八、体会、质疑、建议本次实验主要是对二叉树进行了一系列的操作,归根结底是二叉树的查找、插入、删除。

通过实验我对三种操作有了更加深入的认识,也更加熟练的掌握了其具体应用。

通过对于树这种非链式结构的结构类型各种操作,我也体会到了学以所用的道理。

任何一种结构类型都是为了更加方便准确的对事物进行描述,并且使之能够为计算机所识别使用。

这是一个从具体到抽象的过程,也是一个建模的过程。

而对于一个结构的定义,我认为不应该过分的限制自己一定要使用什么结构。

模型是死的,人是活的。

一切都应该根据具体情况分析使用。

当然,要达到游刃有余的地步,作为我,还有很长的路要走。

具体到这个程序,我发现自己对于引用型的参数认识还不够,特别是具体应用的时候,问题还比较多,应当再继续加强。

九、源代码.cpp文件连接#include<stdio.h>#include<stdlib.h>#define M 100typedef int eletype;typedef struct treenode{eletype data;struct treenode *lson,*rson;}Bnode,*Bptr;int num,found,or,first,last,boundary,breadth;eletype longest,x;Bptr addr;eletype order[M];//找叶子数的函数中:num用于记录叶子数目;按层遍历函数中用于记录层的宽度。

/*found用于记录查找的状态:找父亲函数中:0为查找结点不存在,1为找到该点,2为父亲结点已输出;判断正则树的函数中:1为找到一个不满足的结点,0为未找到;找祖先函数中:0为查找结点不存在,1为找到该点。

*///or与数组order[]配合用于调整输出顺序,使其从根到叶顺序输出。

//first是作为队的首指针。

//last作为队的尾指针。

//boundary作为每层的边界指针。

//breadth记录已遍历的层中最宽的宽度。

//longest用于记录递归到当前,最长路径的值。

//addr用于记录找到的结点的地址。

void preorder(Bptr p)//先序序列输出{if(p==NULL)return;printf("%d ",p->data);preorder(p->lson);preorder(p->rson);}void inorder(Bptr p)//中序序列输出{if(p==NULL)return;inorder(p->lson);printf("%d ",p->data);inorder(p->rson);}void postorder(Bptr p)//后序序列输出{if(p==NULL)return;postorder(p->lson);postorder(p->rson);printf("%d ",p->data);}Bptr precreat()//先序扩充序列造树{Bptr p;scanf("%d",&x);if(x==0)return NULL;p=new Bnode;p->data=x;p->lson=precreat();p->rson=precreat();return p;}Bptr p_i_creat(eletype a[],eletype b[],int i,int j,int s,int t)//先序+中序序列造树{int k;Bptr p;if(i>j)return NULL;p=new Bnode;p->data=a[i];k=s;while((k<=t)&&(b[k]!=a[i]))k++;if(b[k]!=a[i]){printf("输入错误,再见!\n");exit(1);}p->lson=p_i_creat(a,b,i+1,i+k-s,s,k-1);p->rson=p_i_creat(a,b,i+k-s+1,j,k+1,t);return p;}Bptr i_p_creat(eletype a[],eletype b[],int i,int j,int s,int t)//中序+后序序列造树{int k;Bptr p;if(i>j)return NULL;p=new Bnode;p->data=a[j];k=s;while((k<=t)&&(b[k]!=a[j]))k++;if(b[k]!=a[j]){printf("输入错误,再见!\n");exit(1);}p->lson=i_p_creat(a,b,i,i+k-s-1,s,k-1);p->rson=i_p_creat(a,b,i+k-s,j-1,k+1,t);return p;}void findfather(Bptr p,eletype aim)//找结点父亲的函数{if(p==NULL||found==2)return;if(p->data==aim){found=1;return;}if(found==0)findfather(p->lson,aim);if(found==0)findfather(p->rson,aim);if(found==1){printf("%d的父亲是:%d\n",aim,p->data);found=2;}}void leavenumber(Bptr p)//树的叶结点个数{if(p==NULL)return;if(p->lson==NULL&&p->rson==NULL)num++;leavenumber(p->lson);leavenumber(p->rson);}void longest_leave(Bptr p,int height)//找一片最长路径的叶子{if(p==NULL)return;if(p->lson==NULL&&p->rson==NULL&&longest<height){longest=height;addr=p;}longest_leave(p->lson,height+1);longest_leave(p->rson,height+1);}void ancestor(Bptr p,Bptr addr,eletype order[])//存储a结点的祖先(逆序){if(p==NULL)return;if(p==addr){order[or++]=p->data;found=1;return;}if(found==0)ancestor(p->lson,addr,order);if(found==0)ancestor(p->rson,addr,order);if(found==1)order[or++]=p->data;}int degree1(Bptr p)//判断p是否为1度结点,{if(p==NULL)return 0;if(p->lson==NULL&&p->rson!=NULL)return 1;//返回1表示该1度结点有右儿子if(p->lson!=NULL&&p->rson==NULL)return 2;//返回2表示该1度结点有左儿子return 0;//返回0表示该点不是1度结点}void delete_1(Bptr p)//删除一度结点函数{Bptr re;if(p==NULL)return;if(degree1(p->lson)==1){re=p->lson;p->lson=p->lson->rson;delete re;delete_1(p);}else if(degree1(p->lson)==2) {re=p->lson;p->lson=p->lson->lson;delete re;delete_1(p);}if(degree1(p->rson)==1){re=p->rson;p->rson=p->rson->rson;delete re;delete_1(p);}else if(degree1(p->rson)==2) {re=p->rson;p->rson=p->rson->lson;delete re;delete_1(p);}delete_1(p->lson);delete_1(p->rson);}void judge(Bptr p)//判断正则树{if(p==NULL||found==1)return;if(p->lson==NULL&&p->rson!=NULL) {found=1;return;}if(p->lson!=NULL&&p->rson==NULL) {found=1;return;}judge(p->lson);judge(p->rson);}void levelorder(Bptr p,Bptr team[])//按层遍历树的函数{if(p==NULL||first==last)return;first++;printf("%d ",p->data);num++;if(p->lson)team[last++]=p->lson;if(p->rson)team[last++]=p->rson;if(first==boundary){if(breadth<num)breadth=num;num=0;boundary=last;}levelorder(team[first],team);}void initialize()//全局变量初始化函数{num=0,found=0,or=0;longest=-1;addr=NULL;first=-1;last=0;boundary=0;breadth=0;}void main(){Bptr f_root=new Bnode;eletype aim;int i=0,j,s=0,node,choice1,choice2,c;Bptr root,team[M];eletype a[M],b[M];/***************************造树**********************************/ printf("请输入树结点数目:\n");scanf("%d",&node);printf("************************\n");printf("1——先序扩充序列造树\n2——先序+中序序列造树\n3——中序+后序序列造树\n");printf("************************\n");printf("请输入所需操作:");scanf("%d",&choice1);if(choice1==1){printf("请输入先序扩充序列:\n");root=precreat();//先序扩充序列造树}else if(choice1==2){printf("请输入先序序列:\n");for(j=0;j<node;j++)scanf("%d",&a[j]);printf("请输入中序序列:\n");for(j=0;j<node;j++)scanf("%d",&b[j]);root=p_i_creat(a,b,0,node-1,0,node-1);}//先序+中序序列造树else if(choice1==3){printf("请输入中序序列:\n");for(j=0;j<node;j++)scanf("%d",&b[j]);printf("请输入后序序列:\n");for(j=0;j<node;j++)scanf("%d",&a[j]);root=i_p_creat(a,b,0,node-1,0,node-1);}//中序+后序序列造树else printf("输入错误!\n");/***************************造树**********************************/ printf("先序序列:");preorder(root);//先序输出printf("\n");printf("中序序列:");inorder(root);//中序输出printf("\n");printf("后序序列:");postorder(root);//后序输出printf("\n");do{printf("************************\n");printf("1——删除1度结点\n2——找结点的父亲\n3——找根到结点最长路径\n4——统计叶子数\n5——判断正则\n6——按层遍历输出\n");printf("************************\n");initialize();printf("请输入要进行的操作:\n");scanf("%d",&choice2);if(choice2==1){f_root->lson=root;f_root->rson=NULL;delete_1(f_root);//删除1度结点printf("先序序列:");preorder(f_root->lson);//先序输出printf("\n");printf("中序序列:");inorder(f_root->lson);//中序输出printf("\n");printf("后序序列:");postorder(f_root->lson);//后续输出printf("\n");}else if(choice2==2){printf("请输入需要找父亲的结点:\n");scanf("%d",&aim);if(root->data==aim)printf("树根没有父亲!\n");else {findfather(root,aim);//找父亲if(found==0)printf("该结点不存在!\n");}}else if(choice2==3){longest_leave(root,1);//找一片最长路径的叶子ancestor(root,addr,order);//存储叶结点的祖先(逆序)for(or=or-1;or!=-1;or--)//顺序输出printf("%d ",order[or]);printf("为最长路径。

相关文档
最新文档