蓝桥杯真题 左儿子右兄弟(图解、代码详解)

本文探讨如何通过左孩子右兄弟法将多叉树转化为二叉树,关键在于选择每个节点最多孩子的结点作为扩展深度,通过递归实现深度计算。解决算法涉及数据结构搜索和深度优先遍历技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

对于一棵多叉树,我们可以通过“左孩子右兄弟” 表示法,将其转化成一棵二叉树。
如果我们认为每个结点的子结点是无序的,那么得到的二叉树可能不唯一。
换句话说,每个结点可以选任意子结点作为左孩子,并按任意顺序连接右兄弟。
给定一棵包含N 个结点的多叉树,结点从1 至N 编号,其中1 号结点是根,每个结点的父结点的编号比自己的编号小。
请你计算其通过“左孩子右兄弟” 表示法转化成的二叉树,高度最高是多少。
注:只有根结点这一个结点的树高度为0 。

输入格式:

输入的第一行包含一个整数N。
以下N-1 行,每行包含一个整数,依次表示2 至N 号结点的父结点编号。
对于30% 的评测用例,1 ≤ N ≤ 20;
对于所有评测用例,1 ≤ N ≤ 100000。

输出格式

输出一个整数表示答案

思路:

数据结构中学过孩子兄弟表示法,这里类似,父节点的孩子选择第一个作为左孩子,其他的孩子作为第一个孩子的右孩子依次线性连接,只是题目这里改成了,孩子的顺序可以随意选。也就是不必选择第一个孩子作为父节点的左孩子,这个左孩子可以从孩子当中人选,可以画图,容易得出,我们要尽可能的延展树的深度,必须以父节点的孩子中它的孩子数目最多的孩子结点作为尾结点才能延展得更深,如图下例子,1有三个孩子为2,3,4,而2有一个孩子,我们最优的做法就是将1的孩子中孩子数目最多的结点2作为尾结点,才能继续把结点2看作像结点1一样继续延展下去。所以按照思路,可以直接从结点1开始深搜。

 

 所以易得出 树的最大高度=父节点孩子的数目+以它的孩子为父节点的子树的最大高度(递归定义)

代码如下:

#include<iostream>
#include<vector>
using namespace std;
vector<int> f[100050];//f[i]容器中装的是以i结点为父亲的所有孩子结点
int dfs(int node) {
	int count = 0;//存储每一层的孩子的最大孩子数目
	if (f[node].size() == 0) return 0; //递归出口, 似乎也可以不用这一句,到最后一层 count和f[node].size()都为0
	for (int i = 0; i < f[node].size(); i++) {
		count = max(count, dfs(f[node][i]));//求结点孩子的最深层数
	}
	return count + f[node].size();//递归出口,count为node结点孩子的最大孩子数目,f[node].size()是node这一层兄弟数目
}
int main() {
	int n;//n为结点个数
	int t;//
	cin >> n;
	for (int i = 2; i <= n; i++) {
		cin >> t;
		f[t].push_back(i);// i结点的父亲是x结点  所以利用f[t].size()可以求得t结点的孩子数目
	}
	cout << dfs(1);
	return 0;
}

<think>好的,我现在需要解决如何计算使用左孩子兄弟表示法存储的二叉树的高度的问题。首先,我得明确左孩子兄弟表示法的结构特点。根据引用中的信息,这种表示法将多叉树转换为二叉树,其中每个节点的指针指向其第一个孩子,指针指向下一个兄弟节点[^4]。所以,这里的二叉树实际上代表了原多叉树的结构。 接下来,我需要理解二叉树的高度在这个表示法中的含义。由于原多叉树的结构被转换为左孩子兄弟的形式,计算这个二叉树的高度相当于求原多叉树的高度。例如,原树中某个节点的最深层数即为二叉树的高度。 然后,思考如何递归计算高度。对于二叉树中的每个节点,其高度应该是子树的高度加1(因为左孩子对应原树中的子节点),而兄弟节点则处于同一层,所以子树的高度不会影响当前节点的高度。因此,递归算法可能需要比较子树的高度加1和子树的高度,取最大值。 不过,这里可能存在误区。例如,某个节点的兄弟节点虽然在同一层,但它的子树可能有更深的层次。因此,正确的做法应该是对于每个节点,计算其子树的高度加1(代表当前节点在原树中的下一层)和其子树的高度(代表兄弟节点的子树高度),然后取两者中的较大值作为当前节点的高度。递归终止条件应该是当节点为空时返回0。 举个例子,假设有一个二叉树节点A,左孩子是B,兄弟是C。B的左孩子是D,没有兄弟。那么A的高度应该是B的高度+1,而B的高度是D的高度+1,D的高度是1(没有子节点)。同时,C的高度需要考虑它的子树高度。因此,整体高度取决于子树的最大深度和子树的深度。 验证这个思路是否正确,可能需要参考树与二叉树的转换规则。根据引用,孩子兄弟表示法将树转换为二叉树左孩子为第一个子节点,兄弟为下一个兄弟节点[^3][^4]。因此,原树的高度等于转换后的二叉树中最长路径的节点数。而最长路径应该沿着左孩子方向不断向下,直到叶子节点,然后可能通过某个兄弟节点再向下延伸其子树。 因此,递归算法应该遍历每个节点的子树和子树,计算子树的高度加1,同时比较子树的高度(不加1,因为兄弟在同一层),取最大值。这样就能正确得到原树的高度。 最后,编写递归函数:每个节点的高度等于max(子树高度 + 1, 子树高度)。如果节点为空,返回0。这样就能正确计算出左孩子兄弟表示法下的二叉树高度,即原多叉树的高度。</think>### 如何计算左孩子兄弟表示法的二叉树高度 左孩子兄弟表示法将多叉树转换为二叉树,其中: - **指针**指向节点的第一个孩子(对应多叉树的第一个子节点) - **指针**指向节点的下一个兄弟(对应多叉树中同级的下一个节点)[^4] #### 算法思路 1. **递归定义高度**: - 若当前节点为空,返回高度$0$。 - 当前节点的高度由其**子树高度+1**(左孩子对应多叉树中的子节点,深度增加)和**子树高度**(兄弟与原节点同层,深度不变)中的较大值决定。 2. **公式表示**: $$ \text{height}(node) = \max\left(\text{height}(node.\text{left}) + 1,\ \text{height}(node.\text{right})\right) $$ 3. **终止条件**:空节点高度为$0$。 #### 代码示例(Python) ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left # 第一个孩子 self.right = right # 下一个兄弟 def calculate_height(root): if not root: return 0 left_height = calculate_height(root.left) right_height = calculate_height(root.right) return max(left_height + 1, right_height) ``` #### 示例分析 以多叉树为例: ``` A / | \ B C D / \ | E F G ``` 转换为左孩子兄弟表示法的二叉树: ``` A | B -> C -> D | | E -> F G ``` 计算过程: - 节点A的子树高度为`height(B)`,子树高度为`height(C)` - 节点B的子树高度为`height(E)`,子树高度为`height(F)` - 最终高度为3(路径A→B→E或A→B→F或A→D→G) #### 复杂度分析 - **时间复杂度**:$O(n)$,遍历所有节点一次 - **空间复杂度**:$O(h)$,递归栈深度为树的高度 --- ### 相关问题 1. **如何将左孩子兄弟表示法还原为多叉树?** 2. **这种表示法在哪些场景下效率更高?** 3. **如何处理非二叉树结构的树存储?** 4. **左孩子兄弟表示法对树的遍历有何影响?** [^1]: 引用1 [^2]: 引用2 [^3]: 引用3 [^4]: 引用4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值