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

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

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

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

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;
}

给定二叉树的中遍历后序遍历,可以使用这两个列重构原始二叉树,然后进行前序遍历。中遍历的顺是左-根-右,后序遍历的顺是左-右-根。首后序遍历找到根节点,然后用剩余的后序遍历部分在中遍历中定位左右子树。 根据后序遍历的最后一个元素g,我们知道它是根节点,所以在中遍历bdceafgh中g的位置应该对应于它的右子树在中遍历中的位置,即f的左边。由此我们可以确定f是左子树的最后一个元素。接着,我们在中遍历中寻找e,它应该是f的左子树的结束,同时在后序遍历中找到对应的d和c,它们形成了e的左子树。 通过这样的方法,我们可以递归地找到每个节点的位置并构建前序遍历。下面是用Python实现的简单示例: ```python def build_tree(inorder, postorder): def helper(left, right): if left > right: return None root_val = postorder.pop() # 根据后序遍历找根节点 root = TreeNode(root_val) # 创建新节点 mid = inorder.index(root_val) # 在中遍历中找到根节点的位置 root.left = helper(left, mid - 1) root.right = helper(mid + 1, right) return root inorder = inorder.split('') # 将字符串转化为字符列表 postorder = postorder.split('') return helper(0, len(inorder) - 1) class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right # 中遍历为:bdceafhg # 后序遍历为:decbhgf in_order = "bdceafhg" post_order = "decbhgf" root = build_tree(in_order, post_order) pre_order = [] def preorder_traversal(node): if node is not None: pre_order.append(node.val) preorder_traversal(node.left) preorder_traversal(node.right) preorder_traversal(root) print("前序遍历的结果为:", ''.join(pre_order)) # 输出前序遍历结果
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

给个选择

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

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

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

打赏作者

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

抵扣说明:

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

余额充值