无法理解如何使用int类型的递归函数找到二叉搜索树的高度的解释。
对于任何二叉搜索树,给定指向树根节点的指针,其中Node按常规定义如下......
struct Node {
int data;
Node* left;
Node* right;
}
Node* root;
我们可以使用以下int类型的递归函数来给我们二叉搜索树的高度...(函数'max'只需要两个整数并返回两者中的较大者)
int findHeight(Node* root){
if(root == NULL){
return -1;
}
return max(findHeight(root->left),findHeight(root->right)) + 1;
}
int max(int a, int b){
if (a > b)
return a;
else
return b;
}
我的理解是findHeight(root-> left)找到root的左子树的高度,findHeight(root-> right)找到root的右子树的高度,然后max返回更大的子树,因为这将是树的整体高度,加上一个包含将根连接到该子树的边缘。
我对递归很新,所以我决定解压其中一个递归函数调用并尝试理解它。我用一种伪代码方式写出了findHeight(root-> left),每次函数调用自身时都会出现“PAUSE”这个词来表示堆栈上发生的事情,并将下一个函数调用缩进到显示一个新的堆栈帧...(在我的样本BST中,左子树的高度为2)
int fH(Node* root){
if(root == NULL)
return -1;
fH(root->left);
PAUSE
int fH(Node* root){
if root == NULL)
return -1;
fH(root->left);
PAUSE
int fHR(Node*root){
if (root == NULL)
return -1;
fH(root->left);
PAUSE
int fHR(Node* root){
if (root == NULL)
return -1;
fH(root->left);
PAUSE
int fHR(Node* root){
if(root==NULL)
return -1;
}
}
}
}
}
该函数正常工作,但我不明白函数的返回值是如何从-1增长的,这是函数的最终执行返回到2.递归int函数为它们的返回加1每当它们返回到前面的堆栈帧时都会产生值?
我在该短函数中没有看到任何增加函数返回值的内容。我唯一看到的是最后一次通话时它是-1。
如果有人可以尝试向我解释这一点,我真的很感激帮助。非常感谢你。
答案 0 :(得分:2)
函数findHeight返回当前找到的最大高度。
因此,考虑到这一点,最大呼叫是合理的。
在这个动作重演中,我们得到以下函数调用。
所以最后函数findHeight说,这是我当前检查的结束(0高度)。之前的函数调用可以添加他们喜欢的内容。
在我看来,这个功能可以用更直观的方式编写。
也许
int treeHeight(Node* node){
if (!node) // We are not a node.
return 0;
int weAreANode = 1; // Height 1.
int heightLeft = treeHeight(node->left);
int heightRight = treeHeight(node->right);
int theHighestSubtreeHeight = std::max(heightLeft, heightRight);
return weAreANode + theHighestSubtreeHeight;
}
我真的只想再画一些东西。
答案 1 :(得分:1)
我对你的问题的理解是,对于findHeight的每次递归调用,身高是如何增加的,请告诉我这是不是很正确。
通常在C ++中,没有特定的语法将函数定义为递归,而是让程序员通过参数递归地使用它们的函数并返回它们函数的值。
使用此特定功能,看起来增量发生在此行的末尾:
return findHeight(max(findHeight(root->left),findHeight(root->right)) + 1;
返回函数末尾的+1会显式递增递归调用,除了返回int之外,int函数不会执行任何隐式递增。
答案 2 :(得分:1)
您的伪代码错过了PAUSE
之后发生的事情。缺少的是
fH(root->right)
(即使root->right
是nullptr
)max
和特别是,最后一点对于计算树的高度水平至关重要。
如果将这些点添加到伪代码中,您可能会发现它类似于特定树的结构。
答案 3 :(得分:1)
考虑这棵树,
5
/ \
3 10
/ \ /
2 4 8
将使用root 5
调用该函数。
然后将使用3
,2
(左子3
)然后4
(右子3
)来调用它。
2
的高度评估为max(-1, -1) + 1 = 0
,并在3
调用findHeight(root->left)
后返回。 4
也是如此。
对3
(5
的{{1}})的调用现在评估为findHeight(root->left)
。
所以max(0, 0) + 1 = 1
的左孩子的身高为5
。
另一个孩子(右孩子)遵循相同的过程,其中对1
的左孩子的召唤返回10
的高度,而右孩子则返回0
的高度。 -1
max(0, -1) + 1 = 1
将返回5
的{{1}}。
现在回到顶部,findHeight(root->right)
的身高被评估为5
。
答案 4 :(得分:1)
所以考虑一下你的例子,让我们说你有根节点作为' A'左边的节点为' B'和正确的节点为' C'。该计划应返回' 1' -
这是堆栈跟踪 -
findHeight(A)
findHeight(B)
POP findHeight(NULL) returns -1
findHeight(NULL)
用于B的左侧节点,该节点为NULL并返回-1
现在堆栈有 -
findHeight(A)
findHeight(B) max(-1, /*code yet to execute*/) + 1
POP findHeight(NULL) returns -1
findHeight(NULL)
用于B的右侧节点,该节点为NULL并返回-1。
现在堆栈就像 -
findHeight(A)
POP findHeight(B) max(-1, -1) + 1 -> returns 0
此时控件返回到BST的根节点,即节点' A'在执行右节点(节点C)的左节点后,堆栈就像 -
findHeight(A) max(0, /*code yet to execute*/) + 1
findHeight(C)
findHeight(NULL) returns -1
findHeight(NULL)用于C的左侧节点,该节点为NULL并返回-1
现在堆栈有 -
findHeight(A) max(0, /*code yet to execute*/) + 1
findHeight(C) max(-1, /*code yet to execute*/) + 1
POP findHeight(NULL) returns -1
findHeight(NULL)用于B的右边节点,该节点为NULL并返回-1。
现在堆栈就像 -
findHeight(A) max(0, /*code yet to execute*/) + 1
POP findHeight(C) max(-1, -1) + 1 -> returns 0
在完成findHeight(C)之后,控件返回到findHeight(A),现在堆栈已经 -
findHeight(A) max(0, 0) + 1 -> returns 1
你必须添加+ 1,你明确地从你的主要调用函数。
答案 5 :(得分:1)
返回线上发生的事情太多了。让我们重写这样的代码:
int findHeight(Node* root){
if(root == NULL){
return -1;
}
int left = findHeight(root->left);
int right = findHeight(root->right);
int maxval = max(left,right);
return maxval + 1;
}
int max(int a, int b){
if (a > b)
return a;
else
return b;
}
现在,如果我们扩展调用,你可以看到在底部的一个叶子上,左边是-1,右边是-1,然后maxval是-1,它将返回0(因为叶子下面没有任何东西)。然后在底部调用返回0之后,下一级别的最大值将为0,返回的值将为1(因为叶子在下面)。
让我们看一下只留下几个孩子深度的孩子:
int findHeight(Node* root){
if(root == NULL) return -1; // not taken
int left = findHeight(Node* root->left){
if(root == NULL) return -1; // not taken
int left = findHeight(Node* root->left){
if(root == NULL) return -1; // not taken
int left = findHeight(Node* root->left){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // left = -1 at this point (no left children below here)
int right = findHeight(Node* root->right){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // right = -1 at this point (no right children)
int maxval = max(left,right); // left = -1, right = -1
return maxval + 1; // -1 + 1 = 0
} // left = 0 at this point (1 left child below here)
int right = findHeight(Node* root->right){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // right = -1 at this point (no right children)
int maxval = max(left,right); // left = 0, right = -1;
return maxval + 1; // 0 + 1 = 1
} // left = 1 at this point (2 left child below here)
int right = findHeight(Node* root->right){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // right = -1 at this point (no right children)
int maxval = max(left,right); // left = 1, right = -1
return maxval + 1; // 1 + 1 = 2
}