我正在尝试在我的程序中找到二进制搜索树的高度,并继续使用这个递归解决方案来找到高度:
int maxHeight(BinaryTree *p) {
if (!p) return 0;
int left_height = maxHeight(p->left);
int right_height = maxHeight(p->right);
return (left_height > right_height) ? left_height + 1 : right_height + 1;
}
有人可以向我解释一下这是如何运作的吗?我不明白它是如何增加高度的。它看起来应该只穿过树的每一边并返回0。
答案 0 :(得分:2)
算法以这种方式工作: 如果我正在查看的树不存在,那么树的长度为0。
否则,树的长度是我拥有的两个子树的最大高度加1(需要加1才能包含您当前正在查看的节点)。
E.g。如果我有一棵没有树枝的树(即树桩),那么我的高度为1,因为我有两个高度为0的子树,这些高度加上1的最大值为1.
另一个例子: 如果我有一棵树:
A - B - C - D
| |
E F
(其中a是root)
然后,高度不为0,因为A不为空
身高=最大(身高(左),身高(右))+ 1。
A处左边的高度为0,因为A没有左分支。
右分支的高度是B + 1的高度。
计算出B的高度,我们认为B是一棵全新的树:
B - C - D
| |
E F
现在 height = max(height(left),height(right))+ 1。
为了解决左派的问题,我们将E视为一棵全新的树:
E
这是因为它的高度不是0
然而,它的两个分支不存在,所以它的高度为1(每个分支的高度为0)
再次回到父树:
B - C - D
| |
E F
我们正在计算高度,发现左侧分支的高度为1。
所以height = max(1,height(right))+ 1
那么,右边的高度是多少?
再一次,我们认为正确的分支是它自己的树:
C - D
|
F
问题与以前一样 height = max(height(left),height(right))+ 1
计算出高度(左),我们自己考虑F
˚F
F的高度为1,因为它有两个空分支(即最多两个0高度加1)
现在正确看
d
出于同样的原因,D的高度为1
回到F和D的父母:
C - D
|
F
C的高度为:
max(高度(F),高度(D))+ 1
= max(1,1)+ 1
= 1 + 1
= 2。
所以现在我们知道C的高度,我们可以回到父母:
B - C - D
| |
E F
回想一下,我们把B的左分支的长度计算为1,然后开始计算它的右分支高度。
我们现在知道右分支的高度为2
最大值(1,2)为2。
2 + 1 = 3
因此,B的高度为3。
现在我们知道了,我们终于回到原来的树了:
A - B - C - D
| |
E F
我们已经计算出左侧分支高度为0,然后开始处理右侧分支。
我们现在知道右分支的高度为3。
因此, height(a)= Max(height(null),Max(height(B)) =最大(0,3)+ 1 = 3 + 1 = 4
完成。 A的高度为4。
答案 1 :(得分:0)
如果二叉树为空,则该函数仅返回0。这是有道理的,因为如果树为空,则没有要计数的节点,因此高度为0.
如果它不为null,则该函数将向左或右子子树的高度添加1(当前节点的高度),以较大者为准。
它如何知道子子树的高度?通过调用自己递归传递左子项或右子项,以便下一次递归在树中向下开始一级。
第一次在树的根中调用函数时会发生什么?该函数首先调用自身递归地向下移动最左边的子节点,直到它找到叶节点。它再次调用自己传递叶子节点的左子节点,它是null。最后一次调用不再递归,只返回0.函数然后递归到叶子的右子项,它也返回0.然后它为自己的高度加1并返回。
我们现在处于最左边的叶子的父母,并且像以前一样将它递归到正确的孩子(兄弟到叶子)。那个可能不存在(返回0),是叶子(返回1)或有子节点(返回> 1)。无论返回值是什么,它都将与最左边的叶子(高度1)进行比较,以较大者为单位递增(总是添加当前节点的高度)并返回为以当前节点为根的子树的高度节点
请注意,递归将继续“展开”,因为它会返回到根,但在每个级别,它将首先递归到右子子树。这就是所谓的深度优先搜索。最终,将访问整个树,并且突出的最大高度一直计算回根。
答案 2 :(得分:0)
您的代码不符合内存。例如,运行此方法时,height_left
和height_right
变量仍将保存在内存中。那么,如果你运行这个功能数十亿次呢?我建议不返回任何变量,例如
return max(maxHeight(p->left), maxHeight(p->right));