[英]Number of nodes in BST in C
int numOfNodes(struct node* rootPtr){
if(rootPtr== NULL) return 0;
int r = numOfNodes(rootPtr->right);
int l = numOfNodes(rootPtr->left);
return r+l+1;
}
有人可以向我解释这是如何工作的吗? 递归对我来说有点混乱,因为我刚刚开始。 我知道这个 +1 是针对根节点的,但我不明白 r 和 l 是如何增加的。
让我们看看这棵简单的树:
Root
/ \
A B
/ \
C D
然后调用和返回如下:
numOfNodes( Root )
numOfNodes(B)
numOfNodes(D)
return 1
numOfNodes(C)
return 1
return 3
numOfNodes(A)
return 1
return 5
让我们使用一些示例树逐步运行您的代码,变得越来越复杂。
这是一种边缘情况。 如果树是空的,它的根节点是NULL
你可以看到函数会立即返回 0,这是正确的结果。
在这种情况下,我们的树只是一个根节点,我们称之为“A”。 树的结构如下所示:
(A)
/ \
NULL NULL
我们使用NULL
指针作为叶子来标记根节点没有孩子。 让我们继续进行函数调用。
A
作为参数调用numOfNodes
。NULL
,情况不是这样,所以我们继续。A->right
作为参数调用numOfNodes
。
numOfNodes
函数,这次是numOfNodes
rootNode = A->right
A->right
是NULL
。 所以这个对numOfNodes
调用不会超过第一个if
并返回 0。numOfNodes
的初始调用,其中r
现在的值为 0。numOfNodes
,这次使用rootNode = A->left
作为参数。
numOfNodes
调用立即返回 0,因为A->left
是NULL
。numOfNodes
的初始调用,其中l
现在的值为 0r+l+1 = 1
,这是正确的结果>您可能已经注意到,在执行过程中,该函数调用了自身的另一个版本,但其参数与最初调用的参数不同。 这个想法是一种非常强大的编程技术,称为递归,在处理树时特别有用。
本质上,你从树的根开始,让它计算它右边的节点数和左边的节点数,然后加一。 要知道其右侧的节点数,非常简单。 您使用的函数就像右边的节点是一棵新树的根一样。 这可能会导致越来越多地调用同一个计数函数,每次都使用一个更深的节点作为“假根”。 级联调用在到达NULL
节点时停止。 最终,当每个函数返回到调用它的那个函数时,结果“浮回到”树上。
假设我们现在有一个带有更多节点的二叉树。 假设我们有这棵高度为 3 的树:
__(A)__
/ \
(B) (C)
/ \ / \
NULL (D) NULL NULL
/ \
NULL NULL
numOfNodes
,即A
。 A
不是NULL
所以我们继续。A->right
作为参数调用numOfNodes
。numOfNodes
以A->right
作为参数输入numOfNodes
另一个版本(#2)。 事实证明, A->right
是C
,它不是NULL
。 此版本的numOfNodes
不会立即返回 0。numOfNodes
的第三个版本,这次使用C->right
作为参数。C->right
是NULL
所以这个版本(#3)的numOfNodes
返回 0numOfNodes
的第二个版本中的r
变量现在的值为 0l
变量时会发生同样的事情,因为C->left
也是NULL
。numOfNodes
的第二个版本,即用C
调用的版本,到达其最终指令并返回r+l+1
,它等于0+0+1=1
(左侧 0 个节点,右侧 0 个节点,加上“假根“C)。numOfNodes
,因为我们现在知道r
是 1。l
。 为此,我们将再次调用numOfNodes
,这次以A->left
(即B
)作为参数。numOfNodes
四次),并且l
被计算为等于2
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.