【二叉树】二叉树的遍历规则(前序遍历、后序遍历、中序遍历)|前/后/中缀表达式

本文详细介绍了二叉树的前序、中序和后序遍历方法,并通过实例展示了每种遍历方式的特点及应用。此外,还讨论了如何将二叉树的遍历结果转换为前缀、中缀和后缀表达式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://www.cnblogs.com/turnips/p/5096578.html

今天看了一些关于平和查找二叉树的问题,顺便也复习了一下二叉树的遍历规则,写一下学习文档。

树的遍历顺序大体分为三种:前序遍历(先根遍历、先序遍历),中序遍历(中根遍历),后序遍历(后根遍历)。--左总是在右前,根=》前、中、后

 

如图所示二叉树:

 

 

前序遍历:前序遍历可以记为  根左右,若二叉树为空,则结束返回。

 

前序遍历的规则:

(1)访问根节点

(2)前序遍历左子树

(3)前序遍历右子树

 

这里需要注意:在完成第2,3步的时候,也是要按照前序遍历二叉树的规则完成。

前序遍历的输出结果:ABDECF

 

中序遍历:中序遍历可以记为 左根右,也就是说在二叉树的遍历过程中,首先要遍历二叉树的左子树,接着遍历根节点,最后遍历右子树。

同样,在二叉树为空的时候,结束返回。

 

中序遍历的规则:

(1)中序遍历左子树

(2)访问根节点

(3)中序遍历右子树

 

注意:在完成第1,3步的时候,要按照中序遍历的规则来完成。

中序遍历的输出结果:DBEAFC

 

后序遍历:后序遍历可以记为左右根,  也就是说在二叉树的遍历过程中,首先按照后序遍历的规则遍历左子树,接着按照后序遍历的规则遍历右子树,最后访问根节点。

在二叉树为空的时候,结束返回。

后序遍历二叉树的规则:

(1)后序遍历左子树

(2)后序遍历右子树

(3)访问根节点

注意:在完成1,2步的时候,依然要按照后序遍历的规则来完成。

后序遍历的输出顺序:DEBFCA

 

 

一、前缀表达式、后缀表达式、中缀表达式

表达式 a*(b+c)-d是中缀表达式,转化成二叉树后,它是中序遍历的结果
二叉树如下图:
______(-)_________
_____/___\________
____(*)__(d)______
____/__\__________
__(a)__(+)________
______/___\_______
____(b)___(c)_____
后缀表达式,就是后序遍历该二叉树,所得到的序列,也就是:abc+*d-
同样的道理,前缀表达式是前序遍历二叉树,所得到的序列,是:-*a+bcd

 

二、前序遍历、后缀表达式、中缀表达式

前序遍历(DLR)
前序遍历也叫做先根遍历,可记做根左右。
前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。 注意的是:遍历左右子树时仍然采用前序遍历方法。
中序遍历(LDR)
中序遍历也叫做中根遍历,可记做左根右。 中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。
注意的是:遍历左右子树时仍然采用中序遍历方法。
后序遍历(LRD)
后序遍历也叫做后根遍历,可记做左右根。 后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点。在遍历左、右子树时,仍然先遍历左子树,再遍历右子树,最后访问根结点。
注意的是:遍历左右子树时仍然采用后序遍历方法。
<think>好的,我现在需要帮助用户理解二叉树前序、中序和后序遍历的概念、实现以及它们的区别。首先,我需要回顾一下这三种遍历的基本定义,然后考虑它们的递归和非递归实现方法,最后比较它们之间的区别和应用场景。 根据用户提供的引用内容,前序遍历的顺序是根节点、左子树、右子树(DLR),中序遍历是左子树、根节点、右子树(LDR),后序遍历是左子树、右子树、根节点(LRD)。引用[1]中提到,前序序列的第一个元素是整个树的根节点,通过在中序序列中找到根节点的位置来划分左右子树,这在构建二叉树时非常有用。引用[2]讨论了递归和非递归实现,特别是非递归方法中如何处理左路节点和右子树,以及访问根节点的时机不同。引用[3]则解释了遍历顺序的命名规则和基本结构。 接下来,我需要将这些信息整理成一个清晰的回答结构。首先解释每种遍历的概念和访问顺序,然后分别说明递归和非递归的实现方,可能还需要给出代码示例。最后比较它们的区别,比如访问根节点的顺序不同,应用场景的不同(比如前序用于复制树,中序用于二叉搜索树的有序输出等)。 需要注意用户提到的系统级指令,特别是数学表达要用$...$,但这里可能更多的是代码块的使用。需要确保代码示例正确,比如用Python或C++的语法。用户提供的引用中有C++的例子,但用户可能需要通用的解释,或者跨语言的示例。 另外,用户要求生成相关问题,我需要考虑与遍历相关的常见问题,比如如何根据遍历结果重建二叉树,非递归实现的复杂度,遍历的应用等。 在组织内容时,要分点清晰,先讲概念,再讲实现,最后比较区别。同时,引用文献需要自然地插入到相关内容后面,比如在提到前序遍历根节点时引用[1],在讨论非递归实现时引用[2]等。 现在需要检查是否有遗漏的部分,比如层序遍历是否要提及?但用户的问题主要围绕前序、中序、后序,所以可能不需要。但引用[3]提到了层序遍历,可以作为扩展问题。 最后,确保语言简洁,用中文回答,避免使用Markdown格,但代码块需要用指定的格。同时,生成的相关问题要有针对性,帮助用户深入理解。</think>### 二叉树前序、中序、后序遍历详解 #### 一、概念与遍历顺序 1. **前序遍历(DLR)** 访问顺序:根节点 → 左子树 → 右子树 **示例**:若二叉树为 $A(B(D, E), C(F, \emptyset))$(其中 $\emptyset$ 表示空节点),前序遍历结果为 $A \ B \ D \ E \ C \ F$[^1]。 2. **中序遍历(LDR)** 访问顺序:左子树 → 根节点 → 右子树 **示例**:上述二叉树的中序遍历结果为 $D \ B \ E \ A \ F \ C$[^3]。 3. **后序遍历(LRD)** 访问顺序:左子树 → 右子树 → 根节点 **示例**:后序遍历结果为 $D \ E \ B \ F \ C \ A$。 --- #### 二、实现方法 ##### 1. 递归实现(以C++为例) ```cpp // 前序遍历 void preOrder(TreeNode* root) { if (root == nullptr) return; cout << root->val << " "; // 访问根 preOrder(root->left); // 左子树 preOrder(root->right); // 右子树 } // 中序遍历 void inOrder(TreeNode* root) { if (root == nullptr) return; inOrder(root->left); // 左子树 cout << root->val << " "; // 访问根 inOrder(root->right); // 右子树 } // 后序遍历 void postOrder(TreeNode* root) { if (root == nullptr) return; postOrder(root->left); // 左子树 postOrder(root->right); // 右子树 cout << root->val << " "; // 访问根 } ``` ##### 2. 非递归实现(核心思路) - **前序遍历**:使用栈保存右子树,优先访问根节点后再处理左子树[^2]。 - **中序遍历**:先将左路节点全部入栈,出栈时访问根节点,再处理右子树。 - **后序遍历**:需记录上一个访问的节点,确保右子树已处理完毕再访问根节点。 --- #### 三、关键区别 | 遍历 | 根节点访问时机 | 典型应用场景 | |----------|----------------|--------------| | 前序遍历 | 最先访问根节点 | 复制二叉树结构、缀表达 | | 中序遍历 | 中间访问根节点 | 二叉搜索树有序输出、中缀表达式 | | 后序遍历 | 最后访问根节点 | 释放内存资源、后缀表达 | --- #### 四、相关问题 1. 如何通过前序和中序遍历序列重建二叉树? 2. 非递归遍历的时间复杂度是多少?如何优化? 3. 为什么中序遍历对二叉搜索树特别重要? 4. 层序遍历三种遍历有何本质区别? : 前序序列的第一个元素是根节点,用于划分左右子树结构。 [^2]: 非递归实现通过栈模拟递归过程,访问根的时机决定遍历类型。 : 三种遍历本质是深度优先搜索,而层序遍历属于广度优先搜索。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值