用递归,非递归两种方法遍历二叉树

合集下载

二叉树后序遍历的递归和非递归算法

二叉树后序遍历的递归和非递归算法

安 徽电气工 程 职 业 技术学 院学报
:薹6 M2 a r 0 c h 0

-X树后序遍历的递归和非递归算法
孙泽宇, 赵国增 , 舒云星・
( 洛阳工业高等专科学校计算机系 , 河南 洛阳 4 10 ) 703
[ 要 ] 论述了二又树后序遍历的递归算法和非递归算法, 摘 对递归算法中的工作栈 的执行过程做 了
Srcbt e t t ie { u r
● 收稿 日期 :0 5—1 0 70 . 2— 2
作者筒介: 孙泽字(97 . 吉林长春人. 17 一) 男。 洛阳工业高等专科学校计算机秉麓师。研究方向: 人工智能。 趟 目增 (97 . 河南越壁人 。 阳工业高等专科 学校计算机 秉麓师 。研究方 向: 1 一) 男。 7 洛 人工智能。
s c br 木e , r h;} t t ie lt 木 i t m te f g
后序遍历二叉树的递归算法如下 :
T p d fs u tBT o e y e e r c in d t
法及执行时栈 的变化情况 , 可设计 出较好 的非递归化算法 , 本文讨论了二叉树后序遍历的递归和非递归
算法。 2 后序遍历二叉树的递归算法
1 后序遍历左子树( ) 若左子树不为空 ) 2 后序遍历右子树( ) 若右子树不为空 ) 3 访问根结点 ( ) 若存在根结点)
二叉树数据结构如下 :
二叉树是数据结构 中最常见 的存储形式 , 在算法与数据结构中经常使用。树与森林都可以转换为 二叉树 , 而遍历算法则是二叉树最重要的操作 。所谓遍历二叉树 , 就是遵从某种次序 , 遍访二叉树 中的
所有结点, 使得每个结点被访问一次 , 而且仅一次。在遍历算法中, 递归算法是最普遍 的, 弄清 了递归算

遍历二叉树的非递归算法

遍历二叉树的非递归算法

问一次。这里的“ 问”的含义很广 ,比如修 改或输出结点的信息, 访 删除结 我们知道 , 二叉树有三个基本的组成部分, 根, 即: 左子树和右予 树, 只 要依次遍历这三个 部分, 能遍历整个二叉树 。 遍历二叉树的方式通常有 就
算, 所用到的数据仅为整型或实型即能满足要求 , 计算求精课程称作数值方 点等等。
子树, 再访问右子树 , 最后访 问根结 点) 。由于二叉树定义 的递归性, 我们很 容易就会想到用递 归算法来遍历二叉树。 设二叉树与栈 的结构如下 ( c 用 语言描述) :
t p d fs r c i N d y e e tu t B T o e f
c a d t h r a a:
据结构会对应复杂程度不 同的算法 ,丽设计一个合适 的数据 结构 能使算法 三 种, 先序遍历 ( 即: 先访 问根 结点, 再访问左子树 , 最后访问右子树) 中序 、 先访问左 予树 , 再访 问根结点, 后访 问右子树) 后序遍历 ( 最 。 先访问左 的复杂程度大大降低。 编程人员在实践 中体会到 ; 学好~种高级语言仪能解 遍历 ( 决三成所遇到的 问题, 而学好数据结构却 能解 决八成所遇 到的问题, 因此, 在软件 设计中选择一个合适的数据结构越发显得重要 。 在 管理科学领域中, 很多问题都可 以转化 为树 T e r e型结构 , 而多叉树
就会不同。
)A r ys q e c [a ] ra , eu n eM x
t p d f tu t y e e s r c
树, 它有 4 个结点。为了便于理解遍历思想 , 暂时为每个没有 予树 的结点都

e ely e b s 1 Ⅱ p 赤 a e: t e e t p *t p' lmye o ,

golang 中序遍历 递归非递归

golang 中序遍历 递归非递归

golang 中序遍历递归非递归中序遍历是二叉树遍历的一种方式,以左子树、根节点、右子树的顺序访问节点。

在Golang中,我们可以使用递归和非递归两种方式实现中序遍历。

一、递归实现中序遍历递归实现中序遍历是最简单直观的方式。

我们可以定义一个递归函数,用于按中序遍历访问树的节点。

```gopackage mainimport "fmt"type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode}func inorderTraversal(root *TreeNode) {if root != nil {inorderTraversal(root.Left)fmt.Printf("%d ", root.Val)inorderTraversal(root.Right)}}func main() {// 构造一棵二叉树root := &TreeNode{Val: 1}root.Left = &TreeNode{Val: 2}root.Right = &TreeNode{Val: 3}root.Left.Left = &TreeNode{Val: 4}root.Left.Right = &TreeNode{Val: 5}fmt.Println("中序遍历结果:")inorderTraversal(root)}```以上代码中,我们先构造了一棵二叉树,然后调用`inorderTraversal`函数进行中序遍历。

递归函数首先检查根节点是否为空,如果不为空,则按照左子树、根节点、右子树的顺序递归调用自身。

二、非递归实现中序遍历非递归实现中序遍历使用栈来模拟递归的过程。

具体实现过程如下:```gopackage mainimport "fmt"type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode}func inorderTraversal(root *TreeNode) { stack := []*TreeNode{}cur := rootfor len(stack) > 0 || cur != nil {for cur != nil {stack = append(stack, cur)cur = cur.Left}cur = stack[len(stack)-1]stack = stack[:len(stack)-1]fmt.Printf("%d ", cur.Val)cur = cur.Right}}func main() {// 构造一棵二叉树root := &TreeNode{Val: 1}root.Left = &TreeNode{Val: 2}root.Right = &TreeNode{Val: 3}root.Left.Left = &TreeNode{Val: 4}root.Left.Right = &TreeNode{Val: 5}fmt.Println("中序遍历结果:")inorderTraversal(root)}```以上代码中,我们定义了一个栈和一个指针`cur`,其中栈用于存储遍历过程中的节点。

c语言实现二叉树的四种遍历和求深度与叶子个数

c语言实现二叉树的四种遍历和求深度与叶子个数

c语言实现二叉树的四种遍历和求深度与叶子个数二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。

在C语言中,我们可以使用指针来实现二叉树的操作。

本文将介绍四种常见的二叉树遍历方式,以及如何求解二叉树的深度和叶子节点个数。

首先,我们需要定义一个二叉树节点的结构体,包含一个数据域和两个指针域,分别指向左子节点和右子节点。

代码如下:```cstruct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;};```接下来,我们可以实现二叉树的四种遍历方式:前序遍历、中序遍历、后序遍历和层序遍历。

前序遍历是指先访问根节点,然后递归地遍历左子树和右子树。

代码如下:```cvoid preorderTraversal(struct TreeNode* root) {if (root == NULL) {return;}printf("%d ", root->data);preorderTraversal(root->left);preorderTraversal(root->right);}```中序遍历是指先递归地遍历左子树,然后访问根节点,最后递归地遍历右子树。

代码如下:```cvoid inorderTraversal(struct TreeNode* root) {if (root == NULL) {return;}inorderTraversal(root->left);printf("%d ", root->data);inorderTraversal(root->right);}```后序遍历是指先递归地遍历左子树和右子树,最后访问根节点。

代码如下:```cvoid postorderTraversal(struct TreeNode* root) {if (root == NULL) {return;}postorderTraversal(root->left);postorderTraversal(root->right);printf("%d ", root->data);}```层序遍历是按照树的层次逐层遍历节点。

二叉树后序遍历的非递归算法

二叉树后序遍历的非递归算法

二叉树后序遍历的非递归算法
二叉树后序遍历是指按照左子树、右子树、根节点的顺序遍历二叉树的过程。

与前序遍历和中序遍历不同,后序遍历需要考虑根节点的位置,因此需要使用栈来存储节点信息。

非递归算法一般使用栈来实现,因为后序遍历的过程中需要先遍历左子树和右子树,最后才遍历根节点,所以存储节点信息的栈需要进行一些特殊处理。

下面是二叉树后序遍历的非递归算法:
1. 创建一个空栈,并将根节点入栈。

2. 创建一个辅助变量pre表示上一个被遍历的节点。

3. 当栈不为空时,取出栈顶元素top,判断它是否为叶子节点或者它的左右子节点都被遍历过了(被遍历过的节点可以通过辅助变量pre来判断)。

4. 如果top为叶子节点或者它的左右子节点都被遍历过了,则将top出栈,并将它的值输出。

5. 如果不满足条件3,判断top的右子节点是否为pre,如果是,则说明右子树已经遍历完了,此时可以直接输出top的值,并将top出栈;如果不是,则将top的右子节点入栈。

6. 将top的左子节点入栈。

7. 将上一个被遍历的节点pre更新为top。

根据这个算法,我们可以分别对左子树和右子树进行遍历,并保证根节点最后被遍历到,从而实现二叉树的后序遍历。

这个算法的时间复杂度为O(n),空间复杂度为O(n)。

总的来说,二叉树的后序遍历是一种比较复杂的遍历方式,需要使用栈保存节点信息,并且需要特殊处理根节点的位置。

使用非递归算法实现后序遍历可以优化空间复杂度和避免栈溢出的问题。

二叉树的遍历学习心得 (4)

二叉树的遍历学习心得 (4)

二叉树的遍历学习心得 (4)二叉树是一种重要的数据结构,在计算机科学领域中被广泛应用。

对二叉树的遍历是对树进行操作和处理的重要方法之一。

二叉树遍历包括先序遍历、中序遍历和后序遍历三种,每种遍历方式都有它的特点和应用场景。

在本文中,我将结合自己的学习经历,介绍二叉树遍历的相关知识,并分享我的学习心得。

一、什么是二叉树遍历?二叉树遍历指的是按照某种次序访问二叉树的所有节点。

具体来说,遍历过程中所有节点都会被访问且只会被访问一次。

遍历是二叉树最基本的操作之一,它能够帮助我们遍历整个二叉树,并且可以实现二叉树的各种功能。

二、二叉树遍历的种类1. 先序遍历:先访问根节点,然后按照左子树到右子树的顺序依次访问所有的节点。

2. 中序遍历:按照左子树、根节点、右子树的顺序依次访问所有的节点。

3. 后序遍历:按照左子树、右子树、根节点的顺序依次访问所有的节点。

在学习二叉树遍历时,首先需要掌握各种遍历方式的定义和遍历过程。

我们需要了解如何通过递归或非递归的方式来实现二叉树的遍历。

三、学习心得在学习二叉树遍历时,我发现遍历过程中需要注意以下几点:1. 二叉树的遍历是递归算法的经典应用之一。

在递归调用时,需要注意传递和保存上一层函数中的参数和变量,以及返回值的传递和处理。

2. 在遍历时需要针对每个节点进行相应的操作,比如修改节点值、计算节点的数值、输出节点信息等等。

3. 非递归遍历时需要使用栈或队列辅助存储节点信息,在遍历时需要注意栈或队列的操作和数据结构实现。

通过实践,我逐渐掌握了二叉树遍历的基本思想,学会了如何根据需要选择不同的遍历方式。

同时,我也深刻体会到学习算法需要循序渐进、一步步地进行,并且需要强化巩固,多多实践才能真正掌握。

四、总结二叉树遍历是数据结构中的重要主题之一,是学习和掌握二叉树等数据结构算法的基础。

学习时需要理解各种遍历方式的定义和遍历过程,对递归和非递归实现进行深入的练习和掌握,通过不断地巩固和实践,最终能够掌握二叉树遍历的基本思想和实现方法。

非递归中序遍历二叉树课件

非递归中序遍历二叉树课件
由于在非递归实现中,我们使用栈来 模拟递归的过程,因此遍历后的结果 与递归实现相同。
04 非递归中序遍历 二叉树的复杂度 分析
时间复杂度
最好情况:O(n) 最坏情况:O(n)
平均情况:O(n)
空间复杂度
最好情况:O(1) 最坏情况:O(n)
平均情况:O(n)
05 非递归中序遍历 二叉树的优缺点
优点
01
02
03
空间效率高
非递归算法通常只需要常 数级别的额外空间,相比 之下,递归算法可能需要 更多的堆栈空间。
代码简洁
非递归算法的代码通常更 简洁,更易于理解和维护。
适合处理大型数据
由于非递归算法不需要大 量的堆栈空间,因此更适 合处理大型数据集。
缺点
编程技巧要求高
非递归算法需要更多的编程技巧, 特别是对于那些不熟悉这种技术 的人来说,理解和实现可能会比 较困难。
遍历过程
01
02
03
04
弹出栈顶元素,访问该 节点。
如果该节点右子节点存 在,将右子节点入栈。
如果该节点左子节点存 在,将左子节点入栈。
重复上述步骤,直到栈 为空。
遍历后的结果
01
中序遍历的顺序为:左子树 -> 根节点 -> 右子树。
02
非递归方法利用了栈的性质,实 现了从上到下、从左到右的遍历 顺序。
THANKS
感谢观看
栈为空。
实例二:复杂的二叉树
总结词:进阶应用
详细描述:对于复杂的二叉树,非递归中序遍历需要 更加细致的处理。由于树的形状可能不规则,我们需 要更加灵活地使用栈来处理节点之间的关系。在遍历 过程中,我们需要注意处理各种特殊情况,例如循环 引用、节点值相等的情况,以避免陷入无限循环或访 问错误的节点。此外,我们还需要注意优化算法的时 间复杂度和空间复杂度,以提高遍历的效率和准确性。

数据结构求二叉树的深度

数据结构求二叉树的深度

数据结构求二叉树的深度二叉树深度是指从根节点到最远叶子节点的最长路径上的节点数量。

求二叉树的深度是一个常见的问题,通常可以用递归或者非递归的方式来解决。

一、递归方法:递归是一种自上而下的解决问题的方式,在求二叉树深度时,可以使用递归来解决。

递归的思路是,对于一个根节点,它的深度等于其左子树和右子树中较大的深度加1下面是递归方法的实现,以Python语言为例:```def get_depth(root):if root is None:return 0left_depth = get_depth(root.left)right_depth = get_depth(root.right)return max(left_depth, right_depth) + 1```该递归函数的基本情况是,如果根节点为空,则深度为0;否则,递归计算左子树和右子树的深度,并取较大值,最后加1即为整个二叉树的深度。

二、非递归方法:非递归方法是一种自下而上的解决问题的方式,在求二叉树深度时,可以使用非递归的方式来解决。

非递归的思路是,使用层次遍历的方式遍历二叉树的每一层,每遍历一层,深度加1,直到遍历完所有节点。

下面是非递归方法的实现,以Python语言为例:```def get_depth(root):if root is None:return 0depth = 0queue = [root]while queue:depth += 1level_size = len(queue)for _ in range(level_size):node = queue.pop(0)if node.left:queue.append(node.left)if node.right:queue.append(node.right)return depth```该非递归函数的基本思路是,首先判断根节点是否为空,如果为空则深度为0;否则,初始化深度为0和一个队列,将根节点入队,然后进入循环,每一次循环代表一层,首先将循环变量level_size设置为队列的长度,然后将队头元素出队,并将其左右子节点入队,直到队列为空。

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

一、设计思想递归实现二叉树遍历的思想:1.要遍历二叉树首先的问题是创建二叉树。

二叉树的创建可以采用很多的方法。

例如:先序,中序,后序,还可以采用层次的方法创建二叉树。

本程序采用的是先序递归的方式创建的二叉树。

2.然后是中序,先序,后序递归遍历二叉树。

递归的思想是一直调用方法本身。

3.中序递归遍历二叉树的思想是先访问左子树,然后访问根节点,最后访问右子树。

当访问左子树或是右子树的时候,实际上调用的是函数本身。

在这里就体现了递归的思想,当函数的返回值是0的时候,则返回上一次的程序,继续执行下面的语句。

4.先序递归遍历二叉树的思想是先访问根节点,然后访问左子树,最后访问右子树。

同样如步骤3的方式相同,当访问左子树或者是右子树的收,实际上调用的是函数本身,直到返回值是0的时候,返回上一层的程序继续执行。

5.后序递归遍历二叉树的思想是先访问左子树,然后访问右子树,最后访问根节点。

同样跟步骤3的方式相同,当访问左子树或者右子树的时候实际上是调用的是方法本直到有返回值的时候才返回上一层的程序,继续执行.非递归实现二叉树遍历的思想:1.跟递归遍历二叉树的前提一样,首先应该创建一个二叉树,同样使用先序递归的方式创建二叉树。

2.然后是中序,先序,后序非递归遍历二叉树。

3.中序非递归遍历二叉树的思想是:首先是根节点压栈,当根节点的左子树不是空的时候,左子树压栈。

直到左子树为空的时候,不再压栈。

将栈顶元素出栈,访问栈顶元素,并将栈顶的右子树进栈。

当右子树的左子树不是空的时候,左子树一直进栈,直到左子树为空,则不再进栈。

重复上面的操作,直到栈空的时候。

4.先序非递归遍历二叉树的思想是:首先是根节点进栈,然后当栈不为空的时候,将栈顶元素出栈,然后访问。

同时将出栈元素的右子树进栈,左子树进栈。

重复上面的操作,直到栈为空。

5.后序非递归遍历二叉树的思想:首先是根节点进栈,当根节点的左子树不为空的时候,左子树进栈,直到左为空的时候,左子树不再进栈。

指针指向的是右子树,当右子树为空的时候,直接访问根节点。

当右子树不为空的时候,则右子树的指针进栈,当右子树的左子树不为空的时候,则左也进栈,直到左为空。

重复上面的操作,直到栈为空的时候,则遍历树完成。

二、算法流程图递归方法遍历二叉树的流程图如图1图1 递归方法遍历二叉树流程图非递归先序遍历二叉树流程图图2:非递归先序遍历二叉树流程图后序非递归遍历二叉树流程图如图3图3 后序非递归遍历二叉树流程图中序非递归遍历二叉树流程图4图4:中序非递归遍历二叉树流程三、源代码用递归的方式实现二叉树的遍历#include "stdio.h"#include "conio.h"#include <stdlib.h>/*定义二叉树*/typedef struct node{char data;struct node *lchild, *rchild;}BinTnode;typedef BinTnode * BinTree; //定义二叉树类型的指针/*先序创建二叉树*/int CreateBinTree(BinTree *T){ /*BinTree本身是一种类型,是一个指针,是指向结果体指针的类型*/ //这算是问题一//问题二是:关于栈的各种各样的操作,进栈,进的应该是指向树根的指针//问题三是:为什么要定义一个指向指针的指针char ch;*T=(BinTree)malloc(sizeof(BinTnode));if(!*T) printf("overflow");do{ch=getchar();if(ch==' '){ *T=NULL;return 0;}else{(*T)->data=ch;CreateBinTree(&((*T)->lchild));CreateBinTree(&((*T)->rchild));return 1;}}while(ch!='\0');}/*中序递归遍历*/void InorderTransverse(BinTree s){if (s){InorderTransverse(s->lchild);printf("%c", s->data);InorderTransverse(s->rchild);}}//先序递归遍历二叉树void PreOrderTranverseTree(BinTree s){if (s){printf("%c", s->data);PreOrderTranverseTree(s->lchild);PreOrderTranverseTree(s->rchild);}}//后序递归遍历二叉树void PostOrderTranverseTree(BinTree s){if (s){PreOrderTranverseTree(s->lchild);PreOrderTranverseTree(s->rchild);printf("%c", s->data);}}/*主方法*/void main(){BinTree T;printf("请按照先序的顺序输入要创建的树:\n");CreateBinTree(&T); /*中序序列创建二叉树*/printf("中序递归遍历的序列是:");InorderTransverse(T);printf("\n");//先序递归遍历printf("先序递归遍历的序列是:");PreOrderTranverseTree(T);printf("\n");//后序递归遍历printf("后序递归遍历的序列是:");PostOrderTranverseTree(T);printf("\n");用非递归的方式实现二叉树的遍历#include "stdio.h"#include "conio.h"#include <stdlib.h>/*定义二叉树*/typedef struct node{char data;struct node *lchild, *rchild;}BinTnode;typedef BinTnode * BinTree; //定义二叉树类型的指针/*栈的相关操作*/typedef struct{BinTree data[100];int top;}SeqStack;/*初始化栈*/void initStack(SeqStack *S){S->top =-1;}/*进栈*/void Push(SeqStack *S,BinTree x){ /*无论是进栈还是取栈顶元素都应该是指向树的指针*/if(S->top==100-1){printf("the stack is overflow");}else {S->top=S->top+1;S->data[S->top]=x;}}/*出栈*/int Pop(SeqStack *S,BinTree *p){if(S->top==-1){printf("the stack is underflow");return 0;}else {*p=S->data[S->top];--S->top;return 1;}}/*判断栈是不是空*/int EmptyStack(SeqStack S){if(S.top==-1) return 1;else return 0; /* 栈不空的情况*/}/*取出栈顶元素*/int GetTop(SeqStack S,BinTree *p){ //如果栈顶元素取到的是一颗子树的话,那应该返回的是。

,栈顶取到的到底应该是什么哈if(S.top==-1){printf("the stack is empty");return 0;}else {*p=S.data[S.top];return 1;}//访问结点char visit(BinTree p){return (*p).data;}/*创建二叉树*/int CreateBinTree(BinTree *T){ /*BinTree本身是一种类型,是一个指针,是指向结果体指针的类型*/ //这算是问题一//问题二是:关于栈的各种各样的操作,进栈,进的应该是指向树根的指针//问题三是:为什么要定义一个指向指针的指针char ch;*T=(BinTree)malloc(sizeof(BinTnode));if(!*T) printf("overflow");else{do{ch=getchar();if(ch!=’ ’)*T=NULL;return 0;else{(*T)->data=ch;CreateBinTree(&((*T)->lchild));CreateBinTree(&((*T)->rchild));return 1;}}while(ch!='\0');}}/*中序非递归遍历*/void InorderTransverse(BinTree T){SeqStack S;BinTree p;initStack(&S);//初始化栈printf("中序非递归序列是:");Push(&S,T); //根指针进栈T为指向二叉树的指针while(!EmptyStack(S)){ //栈不是空的情况while(GetTop(S,&p) && p)Push(&S,p->lchild); //gettop得到的结果也必须是一棵子树才行,进栈应该进的是树根的指针Pop(&S,&p);if(!EmptyStack(S)){//printf("%c",visit(p));Pop(&S,&p);printf("%c",visit(p));Push(&S,p->rchild);}}}/*先序非递归遍历*/void PreorderTransverse(BinTree T){SeqStack S;BinTree p;initStack(&S);//初始化栈Push(&S,T); //根指针进栈T为指向二叉树的指针printf("先序非递归序列是:");while(!EmptyStack(S)){Pop(&S,&p); //根节点出栈if(p!=NULL){printf("%c",visit(p));Push(&S,p->rchild);Push(&S,p->lchild);}}}/*后序非递归遍历*/void PostorderTransverse(BinTree T){SeqStack S;BinTree p,q;initStack(&S);//初始化栈p=T;printf("后序非递归序列是:");while(p ||!EmptyStack(S)){ //跳出while循环的原因是因为左子树或者右子树为空了if(p!=q){while(p!=NULL){Push(&S,p);if(p->lchild!=NULL)p=p->lchild;elsep=p->rchild;}}if(EmptyStack(S)) break;GetTop(S,&q);if(q->rchild==p){ //进栈的是右子树Pop(&S,&p);printf("%c",visit(p));p=q;}else{p=q->rchild;}}}/*主方法*/void main(){BinTree T;printf("请按照先序的顺序输入创建的树:\n");/*创建树*/CreateBinTree(&T);//中序非递归遍历InorderTransverse(T);printf("\n");//先序非递归遍历PreorderTransverse(T);printf("\n");//后序非递归遍历PostorderTransverse(T);}四、运行结果非递归方法遍历二叉树的运行结果如图5图5非递归方法遍历二叉树的结果图递归方法遍历二叉树的结果图如图6图6递归遍历二叉树的结果图五、遇到的问题及解决•首先遇到的问题是指针的问题以及指向指针的问题。

相关文档
最新文档