繁体   English   中英

C中BST中的节点数

[英]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->rightNULL 所以这个对numOfNodes调用不会超过第一个if并返回 0。
  • 我们回到对numOfNodes的初始调用,其中r现在的值为 0。
  • 然后我们第三次调用numOfNodes ,这次使用rootNode = A->left作为参数。
    • 类似地,这个对numOfNodes调用立即返回 0,因为A->leftNULL
  • 我们返回对numOfNodes的初始调用,其中l现在的值为 0
  • 我们现在可以返回最终结果:左侧节点数 (0)、右侧节点数 (0) 加上我们当前所在的节点数 (1)。 r+l+1 = 1 ,这是正确的结果>

您可能已经注意到,在执行过程中,该函数调用了自身的另一个版本,但其参数与最初调用的参数不同。 这个想法是一种非常强大的编程技术,称为递归,在处理树时特别有用。

本质上,你从树的根开始,让它计算它右边的节点数和左边的节点数,然后加一。 要知道其右侧的节点数,非常简单。 您使用的函数就像右边的节点是一棵新树的根一样 这可能会导致越来越多地调用同一个计数函数,每次都使用一个更深的节点作为“假根”。 级联调用在到达NULL节点时停止。 最终,当每个函数返回到调用它的那个函数时,结果“浮回到”树上。

第三个例子:更完整的树

假设我们现在有一个带有更多节点的二叉树。 假设我们有这棵高度为 3 的树:

        __(A)__
     /          \ 
    (B)         (C)
   /   \       /   \
 NULL  (D)   NULL  NULL
      /   \             
    NULL  NULL
  • 我们首先在树的根上调用numOfNodes ,即A A不是NULL所以我们继续。
  • 我们以A->right作为参数调用numOfNodes
  • 因此, numOfNodesA->right作为参数输入numOfNodes另一个版本(#2)。 事实证明, A->rightC ,它不是NULL 此版本的numOfNodes不会立即返回 0。
  • 我们将进入numOfNodes第三个版本,这次使用C->right作为参数。
  • 事实证明C->rightNULL所以这个版本(#3)的numOfNodes返回 0
  • 所以numOfNodes的第二个版本中的r变量现在的值为 0
  • 当我们计算l变量时会发生同样的事情,因为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
  • 因此,总结果为 4(右侧有 1 个节点,左侧有 2 个节点,加上根节点)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM