计算每个节点的树高,帮助我解释这个代码解决方案

Calculate Tree Height at each Node, help me explain this code solution

本文关键字:解释 代码 解决方案 帮助 节点 计算      更新时间:2023-10-16

以下是一个解决方案的代码片段,该解决方案计算二进制树中每个节点的高度,并将高度存储在每个节点中。代码递归遍历树,下面是Node构造函数。

class Node {
public:
int height; // to be set by computeHeight()
Node *left, *right;
Node() { height = -1; left = right = nullptr; }
~Node() {
delete left;
left = nullptr;
delete right;
right = nullptr;
}
};

以下是计算并存储每个Node的高度的函数。我感到困惑的是,如果在施工时,height设置为-1leftHeightrightHeight如何由n->left->heightn->right->height更新?

void computeHeight(Node *n) {
if (n == nullptr) {
return;
}
computeHeight(n->left);
computeHeight(n->right);
int leftHeight = -1;
int rightHeight = -1;
if (n->left != nullptr) {
leftHeight = n->left->height;
}
if (n->right != nullptr) {
rightHeight = n->right->height;
}
n->height = std::max(leftHeight, rightHeight) + 1;

}

这是运行函数computeHeight的主文件

int main() {
Node *n = new Node();
n->left = new Node();
n->right = new Node();
n->right->left = new Node();
n->right->right = new Node();
n->right->right->right = new Node();
n->right->right->right->left = new Node();
computeHeight(n);
delete n;
n = nullptr;
return 0;

}

想象一个叶节点(左边和右边是nullptr(。则n->left != nullptrn->right != nullptr为假,因此计算有效地变为

int leftHeight = -1;
int rightHeight = -1;
n->height = std::max(leftHeight, rightHeight) + 1;

它实际上是

n->height = 0;

现在,由于递归的执行方式,每个节点都会在计算其子节点的高度后计算其高度。想象一个节点有两个子节点,每个子节点都是一个叶节点。我们已经看到叶节点的高度为零。因此,对这样一个节点的计算实际上是

int leftHeight = -1;
int rightHeight = -1;
if (n->left != nullptr) {
leftHeight = 0; // because n->left is a leaf node
}
if (n->right != nullptr) {
rightHeight = 0; // because n->right is a leaf node
}
n->height = std::max(leftHeight, rightHeight) + 1;

这意味着您最终会得到该节点的n->height = 1

等等。这些计算从树叶开始,直到根部达到它的高度。

我们可以用归纳的基本情况来解决这个问题。基本上,让我们从基本情况开始,然后假设任何情况n都有效,我们必须检查情况n+1是否有效。在计算二叉树中节点的高度的情况下,基本情况是当根节点是叶节点时,而对于n+1情况,左侧/右侧节点是n情况。可以认为n是当前节点的高度,n=0是叶节点的基本情况。

当根节点是叶子时,左侧和右侧节点都是nullptr,该方法本质上变成

void computeHeight(Node *n) {
int leftHeight = -1;
int rightHeight = -1;
n->height = std::max(leftHeight, rightHeight) + 1;
}

在这种情况下n->height变为0,这对于叶节点是正确的。现在,当节点是非叶节点时,语句

computeHeight(n->left);
computeHeight(n->right);

在计算之前已经调用。这基本上使得我们假设左侧和右侧节点都已经得到处理,并且它们的高度是正确的。然后,我们可以使用左右节点的高度来计算根节点的高度,这是通过计算的

int leftHeight = -1;
int rightHeight = -1;
if (n->left != nullptr) {
leftHeight = n->left->height;
}
if (n->right != nullptr) {
rightHeight = n->right->height;
}
n->height = std::max(leftHeight, rightHeight) + 1;

这里的技巧是,我们已经在左侧和右侧节点上调用了computeHeight(),这样当我们在当前节点上进行计算时,我们可以安全地假设子节点已经完全得到了照顾。此外,子节点是在根节点之前计算的,因此程序在返回并计算非叶节点之前,将首先向下滴到叶。