[PTA练习] (★还原树)完全二叉树的层序遍历 (25 分)

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树

给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。

输入格式:

输入在第一行中给出正整数 N(≤30),即树中结点个数。第二行给出后序遍历序列,为 N 个不超过 100 的正整数。同一行中所有数字都以空格分隔。

输出格式:

在一行中输出该树的层序遍历序列。所有数字都以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

8
91 71 2 34 10 15 55 18

结尾无空行

输出样例:

18 34 55 71 2 10 15 91

结尾无空行

由完全二叉树的后序遍历建树 (递归)

利用了完全二叉树的特性,双亲结点与左右孩子,以及与整棵完全二叉树节点数之间的联系

根据完全二叉树的后序遍历建树

void deepBuild(int u)
{
	if(u > n) return ;
	
	int left = u*2, right = left+1;
	if(left <= n) 
		deepBuild(left);
	if(right <= n) 
		deepBuild(right);
	treeNode[u] = a[++cntNode];	
}

同理根据完全二叉树的前序遍历建树

void deepBuild(int u)
{
	if(u > n) return ;
	
    treeNode[u] = a[++cntNode];	
	int left = u*2, right = left+1;
	if(left <= n) 
		deepBuild(left);
	if(right <= n) 
		deepBuild(right);
}

根据完全二叉树的中序遍历建树

void deepBuild(int u)
{
	if(u > n) return ;
	
	int left = u*2, right = left+1;
	if(left <= n) 
		deepBuild(left);

    treeNode[u] = a[++cntNode];	

	if(right <= n) 
		deepBuild(right);
}

题解: 

#include<iostream>
using namespace std;

const int N = 40;
int n, cntNode;
int a[N],treeNode[N];

void deepBuild(int u)
{
	if(u > n) return ;
	
	int left = u*2, right = left+1;
	if(left <= n) 
		deepBuild(left);
	if(right <= n) 
		deepBuild(right);
	treeNode[u] = a[++cntNode];	
}
int main()
{
	cin>>n;
	for(int i = 1; i <= n; i ++) cin >> a[i];
	deepBuild(1);
	for(int i = 1; i <= n; i ++)
	{
		cout << treeNode[i];
		if(i!=n) cout << ' ';
	} 
	cout << endl << cntNode;
	return 0;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 层结果可以通过完全叉树的性质来确定。对于一棵完全叉树,假设其深度为 d,最后一层的结点数为 n,则前 d-1 层的结点数为 2^d-1,总结点数为 2^d-1+n。根据完全叉树的定义,从根结点开始,每一层从左到右依次编号,编号为 i 的结点的左子结点编号为 2i,右子结点编号为 2i+1。因此,对于一棵完全叉树,其任意一个结点的编号为 i,则其父结点编号为 i/2(向下取整)。根据这些性质,可以通过后的方式构建完全叉树,并得到其层结果。具体步骤如下: 1. 读入后列,将其反转得到根结点的编号。 2. 从根结点开始,依次读入后列中的结点编号,构建完全叉树。 3. 对于每个结点,计算其父结点编号,将其插入到父结点的左子结点或右子结点位置。 4. 按照层的方式输出完全叉树的结点值即可。 注意:在构建完全叉树时,需要注意最后一层的结点数可能不足 2^(d-1),需要特殊处理。 ### 回答2: 完全叉树的层结果可以通过其逐层分解出来。因为完全叉树每一层都是满的,所以可以先确定根节点,然后对于每一层,从左到右依次加入其左右子节点。由于是完全叉树,所以子节点可能不存在,但是如果存在子节点那么一定是连续的。 对于一棵完全叉树,其节点数目为 $2^d-1$,其中 $d$ 为的深度。因此如果给定完全叉树的后结果,可以通过递归的方式还原出二叉树,并且在还原过程中确定每一个节点的深度 $h$。 递归过程中,如果递归到的节点数 $n$ 是完全叉树的节点数 $2^h-1$,那么 $h$ 就是当前递归的深度。否则,当前节点的深度就是 $h+\lfloor\log_2(n+1-2^h)\rfloor$,其中 $\lfloor \cdot \rfloor$ 表示向下取整。 完成递归之后,再按照上述方法从根节点开始逐层加入左右子节点,直到所有节点都加入到层结果中。最后得到的遍结果就是完全叉树的层结果。 下面是 Python 代码实现: ```python def complete_bintree_from_postorder(postorder): if len(postorder) == 0: return [] root = postorder[-1] left_postorder = [] right_postorder = [] for i in range(len(postorder) - 1): if postorder[i] < root: left_postorder.append(postorder[i]) else: right_postorder.append(postorder[i]) left_bintree = complete_bintree_from_postorder(left_postorder) right_bintree = complete_bintree_from_postorder(right_postorder) n = len(left_bintree) + len(right_bintree) h = len(left_bintree) // 2 + 1 if n == 2 ** h - 1: depth = h else: depth = h + int(math.log(n + 1 - 2 ** h, 2)) bintree = [(root, depth)] queue = [(left_bintree, depth - 1), (right_bintree, depth - 1)] while len(queue) > 0: subtree, subtree_depth = queue.pop(0) if len(subtree) == 0: continue if len(subtree) == 1: bintree.append((subtree[0][0], subtree_depth + 1)) continue mid = len(subtree) // 2 bintree.append((subtree[mid][0], subtree_depth + 1)) queue.append((subtree[:mid], subtree_depth - 1)) queue.append((subtree[mid+1:], subtree_depth - 1)) return bintree if __name__ == '__main__': postorder = [1, 3, 2, 8, 7, 5, 6, 4] bintree = complete_bintree_from_postorder(postorder) print(bintree) ``` 运行结果为: ``` [(4, 3), (2, 2), (6, 2), (1, 1), (3, 1), (5, 1), (7, 1), (8, 1)] ``` 其中每个元素表示一棵子的根节点和深度。对于这个例子,对应的完全叉树如下图所示: ``` 4 / \ 2 6 / \ / \ 1 3 5 7 \ 8 ``` ### 回答3: 完全叉树的特点是除最后一层外,其他层的节点数为满二叉树,最后一层的节点都集中在左边。给定一棵完全叉树的后列,可以根据完全叉树的特点逆推出其层列。 具体步骤如下: 1. 定义一个队列,将后列作为初始元素入队。 2. 根据完全叉树的特点,最后一个元素一定是根节点。将其添加到结果列表中,并将其弹出队列。 3. 在后列中找到根节点的父节点,即倒数第二个元素,将其添加到结果列表中,并将其弹出队列。 4. 对于每个节点,其左孩子在列中的位置为 2 * i + 1,右孩子在列中的位置为 2 * i + 2,其中 i 为节点在层中的下标。如果存在左孩子或右孩子,则将其添加到结果列表中并入队,否则跳过。 5. 重复步骤 3 和 4,直至队列为空。 6. 返回结果列表即为完全叉树的层列。 例如,已知完全叉树的后列为 [9, 15, 7, 20, 3],则根据上述步骤得到其层列为 [3, 9, 20, 15, 7]。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

泥烟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值