完美二叉树的 层序 与 前/中/后 序之间的相互转换

给出完美二叉树(或者完全二叉树)的层序遍历,转换为前中后序

对于一个层序序列中某个下标为u的数,它在二叉树中对应节点的左节点在层序遍历中的下标为2 * u,右节点为2 * u + 1。

根据这个规律,我们就可以构建出一个完美二叉树(因为每个节点在二叉树中的左右关系都清楚了)

接下来就是怎么把对应的数字填到后序遍历,前序遍历和中序遍历的数组里面。

我们通过递归函数遍历 层序序列 ,按上面的规律就可以遍历二叉树的每一个节点,比如从1开始(根节点),2是左节点,3是右节点,依次递推。那么剩下的事情就是遍历每个点的时候该把层序序列中的哪个数放进当前的节点。

设计一个dfs函数,其作用是给当前节点填值。

  • 前序遍历的特点是 : 根 -> 左 -> 右。我们需要先填根节点,再填左子树,再填右子树。
  • 中序遍历的特点是 : 左 -> 根 -> 右。我们需要先填左子树,再填根节点,再填右子树。
  • 后序遍历的特点是 : 左 -> 右 -> 根。我们需要先填左子树,再填右子树,再填根节点。
#include<iostream>
using namespace std;
int curr;
int post[100010];
int pre[100010];
int in[100010];
int n;


//这里注意了!由于curr是post,in,pre的下标,而**u**是a的下标,且u是从1开始的,所以在main函数中输入a的时候,要从1开始输入!
void dfs_post(int u);
{
	if( u > n ) return ;
	dfs_post(2 * u);
	dfs_post(2 *u + 1);
	post[curr ++] = a[u];
	
	
}

void dfs_pre(int u)
{
	if( u > n ) return ; 
	
	pre[curr ++] = a[u];
	
	dfs_pre(2 * u);
	dfs_pre(2 * u + 1);
	
}

void dfs_in(int u)
{
	if( u > n ) return ;
	dfs_in(2 * u);
	in[curr ++] = a[u];
	dfs_in(2 * u + 1);
}

int main()
{
	
	
	cin>>n;
	
	for(int i = 1 ; i <= n ; i++)
	{
		cin>>a[i];
	}
	
	dfs_post(1);
	curr = 0;
	dfs_in(1);
	curr = 0;
	dfs_pre(1);
	curr = 0;
	
	//输出操作省略
	
}

给出前序或中序或后序,转换为层序遍历

这里涉及到创新思维。

可以发现,这个过程就是上一个过程反过来

我们这里拿后序遍历做例子:

post[curr ++] = a[u];

这行代码可以看作是从层序序列\(a\)中拿出一个数填进\(post\)数组里,现在我们的目标是从post数组里拿出数填进\(a\)中。

怎么放进去,就怎么拿出来
所以我们可以直接写成:

a[u] = post[curr ++];

在第二个过程里面,我们同样要注意的是,这里的u是a的下标,curr是post的下标,u从1开始,curr从0开始,所以在main函数里输入post的时候是从0开始输入的,与第一个过程有区别。

补充几点

一、当题目有镜像要求时,只需要将两个递归函数调换一下位置,先递归右子树,再递归左子树

二、填数时,容易将两个下标搞混,这里提供一种记忆方法:
首先,记住,dfs函数的作用是给当前节点填数。
然后我们根据curr的大小进行选择。
在第一个过程中,我们是从层序序列中拿出数填进对应序列里,而dfs(1)的时候,我们要将层序序列第一位放进去,还是拿后序序列举例,根几点是最后填的,这时候curr达到最大值,所以其对应的是后续序列的最后一位,因此curr就是post的下标,而u等于1刚好对应了层序序列的第一位,也是根几点。然后类比到其他序列;
在第二个过程中,拿后续序列举例,将后序转换为层序,u == 1时,应该填进层序的第一位,所以u是a的下标,curr达到最大,对应post的最后一位,所以curr是post的下标。

完结!

如果有错误希望大家能指出,感谢!

posted @ 2026-04-17 11:30  shuiwangrenjia  阅读(7)  评论(0)    收藏  举报