二叉树的前中后序遍历(考试常考)

二叉树遍历的概念

        二叉树的遍历是按某种规则对二叉树的每个节点均只被访问一次,根据根节点访问位置的不同分为三种:先序遍历(根左右)、中序遍历(左根右)、后序遍历(左右根)。
        由于树是通过不断递归生成的结构,在进行二叉树遍历时,也是一个递归遍历的过程。
下面用简单的图讲解三种遍历方式的区别
在这里插入图片描述

二叉树的先序遍历(根->左->右)

       先序遍历的意思是首先访问根节点,首先访问根节点对应的左子树,再访问根节点对应的右子树。在访问左右子树时,此时左右子树作为新的根节点,继续递归访问该根节点的左右子树,如此反复,直到二叉树为空时返回遍历结果。
上图采用先序遍历访问这颗二叉树的详细过程为:
1.访问该二叉树的根节点,访问节点A,将A加入到序列中
2.访问节点A的左子树,即访问节点B,将B加入到序列中(此时B作为新的根节点,是一棵子树)
3.访问节点B的左子树,即访问节点D,将D加入到序列中
4.由于节点D没有左子树和右子树,因此节点D的子树遍历结束,但是对于B这个节点还没有遍历节点B的右子树,因此访问节点E,将E加入到序列中
5.由于节点E没有左子树和右子树,节点E的子树遍历结束,此时节点B作为根节点的左右节点遍历也结束
6.对节点B作为根节点的左右节点遍历结束意味着节点A的左子树遍历结束,此时开始遍历节点A的右子树,首先访问节点C,将C加入到序列中(此时C作为新的根节点,是一棵子树)
7.访问节点C的左子树,即访问节点F,将F加入到序列中
8.因为此时F无左右子树,即对节点F的子树遍历结束,但节点C还没有遍历右子树,因此访问G,至此对A的左右子树遍历完成,二叉树的先序遍历完成。先序遍历得到序列:ABDECFG
图示如下:
在这里插入图片描述

//二叉树先序遍历的递归实现(根-左-右)
void preorder(TreeNode* t){
	if(t == NULL) return ;
	visit(t) //输出t此时的节点值 类似于printf("%d",t->val) 即访问根节点
	preorder(t->left) //访问左子树
	preorder(t->right) //再访问右子树
}

二叉树的中序遍历(左->根->右)

       中序遍历的意思是首先访问根节点的左子树,然后访问根节点,最后访问根节点对应的右子树,即遍历到到一个节点后,将其暂存,遍历完左子树后,再输出该节点的值,然后遍历右子树
上图采用中序遍历访问这颗二叉树的详细过程为:
1.访问二叉树的根节点,找到节点A
2.访问节点A对应的左子树,得到节点B(此时B作为新的根节点,是一棵子树)
3.访问节点B对应的左子树,得到节点D(此时D作为新的根节点,是一棵子树)
4.由于节点D没有左子树,将D加入到序列后,访问D的右子树,由于没有右子树,因此对D的子树遍历完成,即B的左子树遍历完成,回退到D的根节点B,将B加入到序列,然后遍历节点B的右子树
5.访问节点E,由于E没有左子树,即对E的左子树遍历完成,将E加入到序列中,继续访问E的右子树,因为E没有右子树,此时已经完成对节点B的中序遍历,即A的左子树遍历完毕
6.由于A的左子树遍历完毕,将A加入序列,开始遍历A的右子树
7.遍历A的右子树,首先得到节点C
8.对节点C形成的子树首先访问左子树,得到节点F,由于节点F没有左子树,因此将节点F加入到序列中,同时F也没有右子树,此时对C的左子树遍历完成,将C加入到序列
9.遍历节点C的右节点,得到节点G,对G这颗子树没有左子树,将G加入到序列,遍历G的右子树,无右子树,说明对C子树的的遍历完成,也表明对A的右子树遍历完成,整个过程结束
中序遍历得到的序列为:DBEAFCG
图示如下
在这里插入图片描述

//二叉树中序遍历的递归实现(左-根-右)
void inorder(TreeNode* t)
{
	if(t == NULL) return ;
	inorder(t->left);  //左节点
	visit(t);  //根节点
	inorder(t->right); //右节点
}

二叉树的后序遍历(左->右->根)

       后序遍历的意思是首先访问根节点的左子树,然后访问根节点对应的根节点的右子树,再访问根节点,即访问到一个节点后,将其暂存,遍历完左右子树后,再输出该节点的值
上图采用后序遍历访问这颗二叉树的详细过程为:
1.访问二叉树的根节点,找到节点A
2.访问节点A对应的左子树,得到节点B(此时B作为新的根节点,是一棵子树)
3.访问节点B对应的左子树,得到节点D(此时B作为新的根节点,是一棵子树)
4.因为此时D没有左子树也没有右子树,将D加入序列中,代表对D的后序遍历已经结束,并回退到B(此时以B为根节点)
5.访问节点B对应的右子树,得到节点E(此时以E为根节点),此时E没有左子树也没有右子树,将E加入序列,对E子树的后序遍历结束,至此对B节点的左右子树遍历结束,将B加入序列,也表明此时对A的左子树全部遍历结束
6.遍历A的右子树,首先得到节点C(此时以C为根节点)
7.访问节点C对应的左子树,得到节点F(此时以F为根节点)
8.因为此时F没有左子树也没有右子树,将F加入序列中,代表对F的后序遍历已经结束,并回退到C(此时以C为根节点)
9.访问节点C对应的右子树,得到节点G(此时以G为根节点),此时G没有左子树也没有右子树,将G加入序列,对G子树的后序遍历结束,至此对C节点的左右子树遍历结束,将C加入序列,也表明此时对A的右子树全部遍历结束
10.对A的左右子树全部遍历结束,表明整个树的后序遍历结束
后序遍历得到的序列为:DEBFGCA
图示如下:在这里插入图片描述

//二叉树后序遍历的递归实现(左-右-根)
void postorder(TreeNode* t){
	if(t == NULL) return ;
	postorder(t->left); //左节点
	postorder(t->right);  //右节点
	visit(t); //根节点
}

根据先序遍历和中序遍历得到后序遍历

给定先序遍历序列:ABDECFGH及中序遍历序列:DBEACGFH,求后续序列?
由于先序序列是由根—左—右不断递归得到的序列,而中序序列是由左—根—右递归得到的序列,根据两者特性的结合可以得到树的形状,因此可以得到后序遍历的结果
tip:(先序遍历确定一个子树的根节点,而中序遍历根据根节点将一颗子树再次分为左右子树)
1.因为先序遍历的特性可以得到访问的第一个节点一定是该树的根节点,再由中序遍历的特性,只有访问完根节点的左子树再访问根节点的特性再访问右子树,可以利用该特性得到此时根节点的左右子树情况,切分出根节点A的左子树DBE,根节点A的右子树CGFH,此时可以理解为(DBE)A(CGFH)

此时根节点为A
对A的左子树:先序遍历为BDE,中序遍历为DBE
对A的右子树:先序遍历为CFGH,中序遍历为CGFH

2.对A的左子树继续执行上述过程,可以确定B为A的左子树(先序遍历的第一个节点),同时直接根据中序遍历(左-根-右)可以确定D为B的左子树,E为B的右子树,对A的左子树遍历结束
3.对A的右子树递归执行上述过程,可以确定C为A的右子树(先序遍历的第一个节点),根据中序遍历可以确定GFH均为C的右子树,继续递归

此时根节点为C
对C的左子树:先序遍历为空,中序遍历为空
对C的右子树:先序遍历为FGH,中序遍历为GFH

4.对C的右子树递归执行上述过程,利用先序遍历可以确定F为C的右子树,再根据中序遍历确定G为F的左子树,H为F的右子树,遍历结束
在这里插入图片描述

5.根据还原的二叉树的图可以得出后序遍历的结果为DEBGHFCA

根据中序遍历和后序遍历得到前序遍历

给定中序遍历:BDAEGCF 后序遍历:DBGEFCA,求先序序列?
根据后序遍历确定根节点的位置(类似于前序遍历,只是遍历的顺序不一样),再根据中序遍历按根节点切分为左右子树,如此递归直至遍历结束
1.根据后序遍历的最后一个节点可以确定A为该树的根节点,再根据中序遍历的结果切分出A的左子树(BD)和A的右子树(EGCF),即(BD)A(EGCF)

此时根节点为A
对A的左子树:中序遍历为BD,后序遍历为DB
对A的右子树:中序遍历为EGCF,后序遍历为GEFC

2.对A的左子树继续递归执行上述过程,可以确定B为A的左子树(后序遍历的最后一个节点),根据中序遍历可以确定D是B的右子树,遍历结束
3.对A的右子树递归执行上述过程,确定C为A的右子树,再根据中序遍历且分出C的左子树(EG)以及C的右子树(F)

此时根节点为C(A的右子树)
对C的左子树:中序遍历为EG,后序遍历为GE
对C的右子树,中序遍历为F,后序遍历为F

4.继续对C的左子树做递归,可以确定E的C的左子树,且根据中序遍历确定G为E的右子树,遍历结束
因此可以根据中序遍历和后序遍历的结果得出该树
在这里插入图片描述
5.根据还原的二叉树的图可以得出先序遍历的结果为ABDCEGF

leetcode做题链接

二叉树的遍历
1.144.二叉树的前序遍历
2.94.二叉树的中序遍历
3.145.二叉树的后序遍历
重构二叉树
105.从前序和中序遍历序列构造二叉树
106.从中序和后续遍历序列构造二叉树

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据给定的先列:ABDECFGH和列:DBEACGFH,我们可以推导出后列。首先,根据先的特性,我们可以确定根节点为A。然后,根据的特性,我们可以将列分为A的左子树(DBE)和右子树(CGFH)。所以,我们可以得到如下的分割:(DBE)A(CGFH)。接下来,我们可以递归地应用相同的步骤来确定左子树和右子树的后列。对于左子树DBE,我们可以再次使用先列ABDECFGH和列DBEACGFH,得到后列:BEDFCA。对于右子树CGFH,我们可以再次使用先列ABDECFGH和列DBEACGFH,得到后列:GFHCBA。最后,我们将左子树和右子树的后列与根节点A连接起来,得到整个二叉树的后列:BEDFCA GFHCBA A。所以,根据给定的先列和列,我们可以推导出后列为BEDFCA GFHCBA A。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [二叉树(考试常考)](https://blog.csdn.net/qq_59774127/article/details/127888761)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值