递归非递归两种算法遍历二叉树讲解
二叉树后序遍历的递归和非递归算法

安 徽电气工 程 职 业 技术学 院学报
:薹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 访问根结点 ( ) 若存在根结点)
二叉树数据结构如下 :
二叉树是数据结构 中最常见 的存储形式 , 在算法与数据结构中经常使用。树与森林都可以转换为 二叉树 , 而遍历算法则是二叉树最重要的操作 。所谓遍历二叉树 , 就是遵从某种次序 , 遍访二叉树 中的
所有结点, 使得每个结点被访问一次 , 而且仅一次。在遍历算法中, 递归算法是最普遍 的, 弄清 了递归算
中序遍历二叉树t的非递归算法 -回复

中序遍历二叉树t的非递归算法-回复中序遍历是二叉树遍历的一种方法,它的特点是先访问左子树,然后访问根节点,最后访问右子树。
在非递归算法中,我们需要借助栈来实现中序遍历。
下面我们将逐步分析如何用非递归算法中序遍历二叉树。
首先,我们需要了解栈的基本知识。
栈是一种后进先出(LIFO)的数据结构,它有两个基本操作:入栈(push)和出栈(pop)。
在中序遍历中,我们将节点按照遍历顺序依次入栈,然后出栈并访问节点。
接下来,我们来介绍中序遍历二叉树的非递归算法。
我们可以通过模拟递归来实现中序遍历。
首先,我们定义一个栈用于存储待访问的节点。
初始时,将根节点入栈。
在每一次迭代中,我们需要判断栈是否为空。
若不为空,则将栈顶节点出栈,并访问该节点。
然后,我们将栈顶节点的右子树入栈。
接下来,将栈顶节点的左子树依次入栈,直到左子树为空。
下面,我们以一个简单的例子来说明这个过程。
假设我们有如下二叉树t:1/ \2 3/ \ / \4 5 6 7我们使用中序遍历的非递归算法来遍历这棵树。
首先,将根节点入栈,此时栈中的元素为[1]。
然后,循环执行以下步骤:1. 判断栈是否为空,栈不为空,执行以下步骤;2. 将栈顶节点出栈,访问该节点;3. 将栈顶节点的右子树入栈;4. 将栈顶节点的左子树依次入栈,直到左子树为空。
按照这个步骤,我们首先将1出栈并访问,然后将右子树入栈,栈中的元素为[2, 3]。
然后,我们继续将左子树入栈,栈中的元素变为[4, 2, 3]。
此时,我们将4出栈并访问,然后将栈中的元素变为[2, 3]。
接着,我们将2出栈并访问,将右子树入栈,栈中的元素变为[5, 3]。
继续将左子树入栈,栈中的元素为[5, 6, 3]。
接着,我们将5出栈并访问,将栈中的元素变为[6, 3]。
最后,我们将6出栈并访问,将右子树入栈,栈中的元素变为[7, 3]。
最后,我们将7出栈并访问,此时栈为空,遍历结束。
通过这个例子,我们可以看到中序遍历的非递归算法确实按照中序遍历的顺序访问了二叉树的所有节点。
二叉树的遍历ppt课件

后序遍历顺序:
A
B
C
DE
F
中 序遍历 : 资金是运动的价值,资金的价值是随 时间变 化而变 化的, 是时间 的函数 ,随时 间的推 移而增 值,其 增值的 这部分 资金就 是原有 资金的 时间价 值
DBEAF
C
前序遍历: A B D E C F
后序遍历
A
B
C
D EF
二叉树
资金是运动的价值,资金的价值是随 时间变 化而变 化的, 是时间 的函数 ,随时 间的推 移而增 值,其 增值的 这部分 资金就 是原有 资金的 时间价 值
总结:
我们这节课主要采用“案例驱动式”教 学方法讲解了二叉树的遍历,以案例方式讲 解通过其中两种遍历顺序推断出第三种遍历 顺序的分析方法。主要培养大家灵活运用知 识的能力和举一反三的分析能力。
一棵二叉树的中序遍历结果为 DBEAFC,前序遍历结果为ABDECF, 则后序遍历结果为 【 】 。
资金是运动的价值,资金的价值是随 时间变 化而变 化的, 是时间 的函数 ,随时 间的推 移而增 值,其 增值的 这部分 资金就 是原有 资金的 时间价 值
前序遍历:若二叉树非空,则先访问根节点,再 遍历左子树,最后遍历右子树。
资金是运动的价值,资金的价值是随 时间变 化而变 化的, 是时间 的函数 ,随时 间的推 移而增 值,其 增值的 这部分 资金就 是原有 资金的 时间价 值
拓展:
已知二叉树的 后序遍历:D A B E C 中序遍历:D E B A C
请问前序遍历结果为?
资金是运动的价值,资金的价值是随 时间变 化而变 化的, 是时间 的函数 ,随时 间的推 移而增 值,其 增值的 这部分 资金就 是原有 资金的 时间价 值
遍历二叉树的非递归算法

问一次。这里的“ 问”的含义很广 ,比如修 改或输出结点的信息, 访 删除结 我们知道 , 二叉树有三个基本的组成部分, 根, 即: 左子树和右予 树, 只 要依次遍历这三个 部分, 能遍历整个二叉树 。 遍历二叉树的方式通常有 就
算, 所用到的数据仅为整型或实型即能满足要求 , 计算求精课程称作数值方 点等等。
子树, 再访问右子树 , 最后访 问根结 点) 。由于二叉树定义 的递归性, 我们很 容易就会想到用递 归算法来遍历二叉树。 设二叉树与栈 的结构如下 ( 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 个结点。为了便于理解遍历思想 , 暂时为每个没有 予树 的结点都
f
e ely e b s 1 Ⅱ p 赤 a e: t e e t p *t p' lmye o ,
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`,其中栈用于存储遍历过程中的节点。
二叉树后序遍历的非递归算法

二叉树后序遍历的非递归算法
二叉树后序遍历是指按照左子树、右子树、根节点的顺序遍历二叉树的过程。
与前序遍历和中序遍历不同,后序遍历需要考虑根节点的位置,因此需要使用栈来存储节点信息。
非递归算法一般使用栈来实现,因为后序遍历的过程中需要先遍历左子树和右子树,最后才遍历根节点,所以存储节点信息的栈需要进行一些特殊处理。
下面是二叉树后序遍历的非递归算法:
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)。
总的来说,二叉树的后序遍历是一种比较复杂的遍历方式,需要使用栈保存节点信息,并且需要特殊处理根节点的位置。
使用非递归算法实现后序遍历可以优化空间复杂度和避免栈溢出的问题。
非递归中序遍历二叉树课件

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. 定义一个空的辅助栈;2. 从二叉树的跟节点开始循环:a. 将当前节点压入辅助栈;b. 如果当前节点存在左孩子,则将当前节点设置为其左孩子,继续循环;c. 如果当前节点不存在左孩子,则从辅助栈中弹出一个节点,并将该节点的值输出;d. 如果被弹出的节点存在右孩子,则将当前节点设置为其右孩子,继续循环;e. 如果被弹出的节点不存在右孩子,则回到步骤c。
四、中序遍历非递归算法的实现1. 定义一个空的辅助栈和一个指向二叉树跟节点的指针cur;2. 对于每个节点,如果该节点不为空或者辅助栈不为空,则进行循环:a. 如果当前节点不为空,则将其压入辅助栈中,并将当前节点更新为其左孩子;b. 如果当前节点为空,则从辅助栈中弹出一个元素,并输出该元素的值;i. 将当前节点更新为被弹出元素的右孩子。
3. 循环结束后,即可完成对二叉树的中序遍历。
五、代码实现以下是Java语言实现中序遍历非递归算法的代码:```public static void inOrder(TreeNode root) {Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;while (cur != null || !stack.isEmpty()) {if (cur != null) {stack.push(cur);cur = cur.left;} else {cur = stack.pop();System.out.print(cur.val + " ");cur = cur.right;}}}```六、时间和空间复杂度中序遍历非递归算法的时间复杂度为O(n),其中n为二叉树节点的个数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用递归、非递归两种方法遍历二叉树一、设计思想1. 用递归算法遍历设计思想:主要是通过不同程序顺序,从而实现递归的顺序遍历前序遍历:先判断节点是否为空,如果不为空,则输出。
再判断左节点是否为空,如果不为空,则递归调用,直到遍历到最左边。
接着再遍历最左边的右子树,如果此时右子树不为空,则递归遍历左子树的操作,直到遍历到叶子节点。
如果右子树为空,则回溯上次的递归调用,重复输出和遍历右子树的操作。
中序遍历:先遍历左节点是否为空,如果不为空,则递归调用,直到遍历到最左边或者叶子节点,然后输出,接着再遍历最左边的右子树,如果此时右子树不为空,则递归重复遍历左子树的操作,直到遍历到叶子节点。
如果右子树为空,则回溯到上次递归调用,重复输出和遍历右子树的操作。
后序遍历:先判断左节点是否为空,如果不为空则一直递归直到遍历到最左边,然后遍历右节点,再接着遍历到左子树的最右边,直到遍历到叶子节点。
此时输出,回溯到上次递归,继续执行后面的操作,重复,直到将整个树遍历完毕。
2. 用非递归算法遍历设计思想:主要是通过栈的存取,判空,从而实现树的遍历前序遍历:通过一个循环实现。
先输出节点的数值,因为栈的特性,则需要先判断右子树是否为空,如果不为空,则将右子树压栈。
然后判断左子树是否为空,如果不为空,则将左子树压栈。
接着再将栈里面的子树弹出赋给给当前节点变量,重复上述操作,直到栈为空后退出循环。
中序遍历:通过循环实现。
将树一直遍历到最左端,并将中间所经过的节点保存在栈中,当遍历到最左边的时候,则弹出栈里面的子树。
输出数值,将当前节点赋值为当前节点的右子树,遍历右子树,即重复上述操作,直到当前节点为空,并且栈内元素为0。
后序遍历:通过循环和标记栈实现。
将数一直遍历到最左端,并将中间的节点保存在树栈中,同时同步的添加一个标记栈。
当遍历到最左边的时候,弹栈并赋值给当前栈,然后判断标记栈的数值,如果数值为0的话则代表当前树没有遍历过,遍历右子树。
然后重复上面的操作,如果数值为1的话则代表此时数已经遍历过了,可以开始输出了,为了避免重复输出,将当前栈赋为空。
重复循环操作,直到栈内没有元素,且当前节点为空(因为一直左的操作并没有将右子树压栈)。
- 1 -用递归、非递归两种方法遍历二叉树二、算法流程图开开开Root=Tree t Root=Tree t Root=Tree tYYYRoot=nullRoot=nullRoot=nullNNNN输出数NRoot.getRoot.getTree=nullNTree=nullRoot.get YTree=nullY输出数NYRoot.getTree=nullNNRoot.getRoot.get YTree=nullTree=null输出数YY结束结束结束图2 递归算法-后序遍历先序遍历-递归算法图1 图3 递归算法-中序遍历- 2 -用递归、非递归两种方法遍历二叉树开始开Tree t=root Tree t=root NNt = null压t = null outpu YYt=current.getLtree()Nt.getRtree=t=Pus nullstack.Pop()Youtpu Nt.getLtree=Pusnullt=current.getRltree()YNt=栈为Nstack.pop()栈为YY结束结束 -5 -4 图非递归算法先序遍历图非递归算法中序遍历- 3 -用递归、非递归两种方法遍历二叉树开Tree t=rootNt = null标签栈压PushYt=t.getLtree()t=stack.pop()标签栈出赋值给标志N判断栈是否t=t.getRTree(标签栈压经入栈Yt出栈并赋OutputCurrent=nullN树栈为空且当前节点为Y结束-6 图非递归算法后序遍历- 4 -用递归、非递归两种方法遍历二叉树三、源代码#include<stdio.h>#include<stdlib.h>typedef char ElemType;//定义树结构typedef struct tree{ElemType data;struct tree * lchild;struct tree * rchild;unsigned int isOut; //专为后序遍历设置的,0为不需要被输出,1为需要被输出}TreeNode, *Tree;//定义栈结构typedef struct stack{Tree * base;Tree * top;int stacksize;}SqStack;void InitStack( SqStack &s );void Push( SqStack &s, Tree e );void GetTop( SqStack s, Tree &e );void Pop( SqStack &s, Tree &e );int StackEmpty( SqStack s );void CreateTree(Tree &t);void PreOrder(Tree t);void PreOrder1(Tree t);void InOrder(Tree t);void InOrder1(Tree t);void PostOrder(Tree t);void PostOrder1(Tree t);int main(){Tree T;printf(\按先序序列输入结点序列,'*'代表空:);CreateTree(T);printf(\递归先序遍历的结果:);PreOrder(T);- 5 -用递归、非递归两种方法遍历二叉树printf(\非递归先序遍历的结果:);PreOrder1(T);printf(\递归中序遍历的结果:);InOrder(T);printf(\非递归中序遍历的结果:);InOrder1(T);printf(\递归后序遍历的结果:);PostOrder(T);printf(\非递归后序遍历的结果:);PostOrder1(T);printf(\);return 0;}初始化栈void InitStack( SqStack &s ) // {s.base = (Tree *)malloc(100*sizeof(Tree));if ( !s.base ){程序将推出执行!\n); printf(InitStack内存分配出错,exit (-1);}s.top = s.base;s.stacksize = 100;}void Push (SqStack &s, Tree e ) //元素入栈接收一个stack 类型变量和一个tree* 类型变量{if ( s.top - s.base >= s.stacksize ){s.base = (Tree *)realloc(s.base,(s.stacksize+20)*sizeof(Tree));if ( !s.base ){printf(Push内存分配出错,程序将退出执行\n);exit (-1);}// s.top = s.base + s.stacksize;s.stacksize += 20;}e->isOut = 0;*s.top++ = e;}void GetTop( SqStack s, Tree &e ) //获得栈顶元素- 6 -用递归、非递归两种方法遍历二叉树{e = *(s.top - 1); //s.top为tree** 类型}出栈void Pop( SqStack &s, Tree &e ) // {if ( s.top == s.base ){牰湩晴尨栈为空\n);return ;}e = *(--s.top);}int StackEmpty( SqStack s ) //判断栈是否为空{if ( s.top == s.base )return 1;return 0;}//void CreateTree(Tree &t) 以先序序列建立树{ char ch;scanf(%c,&ch);if ( ch == '*' )t = NULL;else{t = (Tree)malloc(sizeof(TreeNode));if ( !t ){); 牰湩晴尨分配内存出错!return ;}t->data = ch;CreateTree(t->lchild);CreateTree(t->rchild);}}// void PreOrder(Tree t) 递归先序遍历,遍历顺序:根、左、右{- 7 -用递归、非递归两种方法遍历二叉树//先访问根节点,再先序遍历左子树,再先序遍历右子树if ( t ) //如果树t 不为空树,才继续执行先序遍历{printf(%c ,t->data);PreOrder(t->lchild);PreOrder(t->rchild);}}递归中序遍历,遍历顺序:左、中、右void InOrder(Tree t) // {//先中序遍历左子树,再访问根节点,再中序遍历右节点t 为空树,则停止向下遍历//如果树if ( t ) {InOrder(t->lchild);printf(%c ,t->data);InOrder(t->rchild);}}//递归后序遍历,遍历顺序:左、右、根void PostOrder(Tree t){if ( t ){PostOrder(t->lchild);PostOrder(t->rchild);printf(%c ,t->data);}}非递归先序遍历void PreOrder1(Tree t) // {为//p 类型变量Tree p = t; tree*SqStack s;InitStack(s);//while ( p || !StackEmpty(s) ) 当树的节点不为空或栈不为空执行循环{ // 当数的此节点不为空时,打印此节点值且将此节点入栈if ( p ){printf(%c ,p->data);Push(s,p);p = p->lchild;}- 8 -用递归、非递归两种方法遍历二叉树else //否则父节点出栈,p指向父节点的右子树{Pop(s,p);p = p->rchild;}}}//非递归中序遍历void InOrder1(Tree t){Tree p = t;SqStack s;InitStack(s);while ( p || !StackEmpty(s) ){if ( p ){Push(s,p);p = p->lchild;}else{Pop(s,p);printf(%c ,p->data);p = p->rchild;}}}void PostOrder1(Tree t) //非递归后序遍历,遍历顺序:左、右、根{// t->isOut = 0; 初始值表示不输出Tree p = t;SqStack s;InitStack(s);或节点非空while ( p || !StackEmpty(s) ) // 栈非空执行循环{if ( p ){if ( p->isOut )左右子树都已输出,则该节点也输出// {Pop(s,p);printf(%c ,p->data);- 9 -用递归、非递归两种方法遍历二叉树if (!StackEmpty(s))GetTop(s,p); //得到该节点元素的父节点elsep = NULL;}else{if ( (p->lchild) && (p->lchild->isOut == 1) ){ , //如果存在左子树并且左子树已经遍历完,则说明该节点已经入栈p->isOut = 1;p = p->rchild;}否则入栈该节点的树,并且走向它的左子树//else{Push(s,p);p = p->lchild;}}}else{GetTop(s,p);if ( p->rchild ){p = p->rchild;}else{Pop(s,p);printf(%c ,p->data);p->isOut = 1;if (!StackEmpty(s)){GetTop(s,p);if ( p->lchild == NULL )// p->isOut = 1;置isOut 右子树已输出,将父节点1}elsep = NULL;}}}}- 10 -用递归、非递归两种方法遍历二叉树四、运行结果7 遍历二叉树运行结果图图五、遇到的问题及解决这部分我主要遇到了如下三个问题,其内容与解决方法如下所列:?第一个问题:递归的使用,没有完全理解递归的含义描述:递归的使用是每次都将上次调用的现场保留,直到本次的方法的完成才会返回上次的调用的现场,由于没有完全的了解,所以在调用的时候回忽略掉上次保存的现场。