前序,中序,后序三种遍历的相互转化(思路+递归实现代码)【全】

在二叉树这种数据结构中,有三种遍历方式,分别是前序(也叫先序)遍历,中序遍历,和后序遍历。当然有的地方还会有按层遍历。

前序遍历:根->左->右
中序遍历:左->根->右
后序遍历:左->右->根
按层遍历:从第一层开始一直到最后一层,类似按着完全二叉树的编号一个一个输出

先说上面前三种遍历的相互转换,
当已知前序遍历序列和中序遍历序列的时候,可以确定它的后序遍历序列。
当已知后序遍历序列和中序遍历序列的时候,可以确定它的前序遍历序列。
但是当已知前序遍历序列和后序遍历序列的时候,它的中序遍历序列不一定
就不唯一,也就是说已知前序和后序不一定能推出中序。
下面会详细讲解已知前序和中序或者已知后序和中序来求另一种序列的思路还代码。

1.已知后序和中序序列求前序序列。

举个栗子,比如说后序序列是3,4,2,6,5,1(左右根)中序序列是3,2,4,1,6,5(左根右)
思路:后序序列的最后一个数字(1)必定为整棵二叉树的根节点,然后在中序序列中找到1的位置可以确定这个根节点的左右子树分别是多少,(此时1的左子树为3 2 4 ,右子数为6 5)然后将3 2 4这颗树在后序序列中寻找可以找到它的左子树的根节点为2,6 5 这颗右子树的根为5以此类推,可以找到所有点。最后得到前序序列:1 2 3 4 5 6 ;
代码如下:

#include<bits/stdc++.h>
using namespace std;
int post[]={3,4,2,6,5,1};
int in[]={3,2,4,1,6,5};
void pre(int root,int start,int end)
{
	if(start>end)	return ;	//退出条件,这棵树的范围为0
	int i=start;
	while(i<end&&in[i]!=post[root])	i++;	//在后序序列中确定根之后在中序序列中找他的所在位置
	printf("%d ",post[root]);	//输出找到的根
	pre(root-1-end+i,start,i-1);	//左子树的根下标即为在后序序列中根节点的位置-右子树的个数(root-(end-i+1))
	pre(root-1,i+1,end);	//根的下标-1就是它的右子树的根的下标(root-1)
}
int main()
{
	pre(5,0,5);
	return 0;
} 
		 
2.已知前序序列和中序序列求后序序列

其实和上面那种类似,只不过前序序列的第一个数就是这颗二叉树的根,然后在中序序列中找到它的所在位置,即可找到这颗二叉树的左右子树,然后以此类推。先打印左子树,后打印右子树,最后输出当前根结点pre[root]的值。
代码如下:

#include<iostream>
using namespace std;

int pre[]={1, 2, 3, 4, 5, 6};//前序序列
int in[]={3, 2, 4, 1, 6, 5};//中序序列

void post(int root,int start,int ends){//后序打印
  if(start>ends)	return;
  int i=start;
  while(i<ends&&in[i]!=pre[root])	i++;//找到中序序列中根结点的位置
  post(root+1,start,i-1);//遍历左子树
  post(root+1+i-start,i+1,ends);//遍历右子树
  cout<<pre[root]<<' ';
}

int main(){
  post(0,0,5);
  return 0;
}

  • 14
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
递归先序中序后序遍历的动画可以通过使用栈来实现。具体实现方法如下: 1. 非递归先序遍历: 1.1 将根节点入栈。 1.2 取出栈顶元素,访问该节点。 1.3 如果该节点有右子树,则将右子树入栈。 1.4 如果该节点有左子树,则将左子树入栈。 1.5 重复步骤 1.2 - 1.4,直到栈为空。 2. 非递归中序遍历: 2.1 将根节点入栈。 2.2 如果当前节点有左子树,则将左子树入栈。 2.3 取出栈顶元素,访问该节点。 2.4 如果该节点有右子树,则将右子树入栈。 2.5 重复步骤 2.2 - 2.4,直到栈为空。 3. 非递归后序遍历: 3.1 将根节点入栈。 3.2 如果当前节点有左子树,则将左子树入栈。 3.3 如果当前节点有右子树,则将右子树入栈。 3.4 取出栈顶元素,访问该节点。 3.5 如果当前节点是栈顶元素的左子节点,则将栈顶元素的左子节点标记为已访问。 3.6 如果当前节点是栈顶元素的右子节点,则将栈顶元素的右子节点标记为已访问。 3.7 如果栈顶元素的左右子节点都已经访问过了,则将栈顶元素出栈,并访问该节点。 3.8 重复步骤 3.2 - 3.7,直到栈为空。 下面是非递归先序中序后序遍历的动画演示: ![非递归先序中序后序遍历动画演示](https://img-blog.csdn.net/20180530163412909?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N6aGFuZ3hp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/85)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给个选择

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值