2011-05-05 51 views
2

计算树中节点数量的函数。该函数如何计算树中节点的数量?

int count(node *t) 
{  
    int i; 
    if (t == NULL)   
     return(0); 
    i = 1 + count(t->left) + count(t->right); // recursion occurs address of left node is passed and 
    return(i);        // continue to pass until whole left node 
}            // is traversed and the value of t is 
               // NULL and 0 is returned same for right node counting 
               // i = 1 + 0 + 0 = 1 

节点数如何计算?

+0

左节点是一个子树。右节点也是一个子树。函数调用自己,子树作为参数,计数递增。现在,当计数器到达叶子时,它没有任何孩子,所以它返回0.意义'叶子树计数'。现在它达到了一级,结果是'1 +左叶数+右叶数'= 3'。同样的,它还有一个更高的层次并且可以得到总数。 **假设所有节点都有离开叶子的左右儿童。那么,概念不会改变** – Mayank 2011-05-05 10:17:38

回答

3

这是计数树节点的递归实现。它被称为根节点,并返回“左子树中的一个正数节点加右子树中的节点数”,这是递归地完成,直到它到达叶节点。

+0

我知道的是递归遍历左子树,直到找到最后一个节点,现在t的值为NULL,并且在count(t-> left)时返回的值对于右子树并返回0来计数(t->右)。现在增加i = 1 + 0 + 0 = 1;那么它如何计算左右节点的总数 – srbh 2011-05-05 10:26:00

+0

@srbh:该键一旦递归调用开始,则前一个调用将暂停“暂停”,并等待递归调用结束,然后使用其结果。所以调用树首先下到叶节点,然后调用以FIFO顺序开始返回并且总结来自子树的节点数量。 – sharptooth 2011-05-05 11:06:44

+0

这意味着为递归调用维护堆栈并继续推送每个节点的地址,直到找到空节点。然后进入count(t-> right)找到正确的节点,直到找到NULL节点。节点的先前地址现在返回到它的父节点,再次计算左右节点,依此类推。请纠正我错在哪里。 – srbh 2011-05-05 11:26:42

1

总数包括当前/根节点加上左分支上的计数加上右分支上的计数。您的哨兵是NULL,这意味着您已经到达您当前正在计数的任何分支的叶节点。然后你放松回来。递归:)

1

首先,你自己试过了吗?

基本上,它为每个非零节点加1。大概是这样的:1 + number_of_nodes_to_the_left + number_of_nodes_to_the_right。这扩展到:1+(1+number_of_nodes_to_the_left_in_left+number_of_nodes_to_the_right_in_left) + (1+number_of_nodes_to_the_left_in_right + number_of_nodes_to_the_right_in_right)。继续扩展,您会看到树中每个非空节点基本上都是1 + 1 + 1 +....

编辑:为了说明这一点,不妨考虑下面的树:

 Node0 
     | 
(left) | (right) 
Node1 _|_ Node2 
      | 
    (left) | (right) 
    Node3 _|_ Node4 

当你这样做int node_count = count(Node0),因为节点0不为空,它关系到return语句是: return 1 + count(left) + count(right)。您需要了解一个基本的事情,即您的递归函数中的某个操作只发生在其他操作之后。换句话说,直到操作count(left)完成后才会发生操作count(right)。现在看看你在那里的return语句,并根据上面的树翻译它。这将是1+count(Node1)+count(Node2)。所以count(Node2)count(Node1)完成之前没有得到计算。因此,对于count(Node1),count函数将以Node1作为参数被调用(再次)。因此,现在让我们忘掉半计算表达式1+count(Node1)+count(Node2)(我们稍后再回来)。

现在对于count(Node1),Node1不是NULL,因此进入return语句。这将(再次)是1+count(left)+count(right)。但是等一下,Node1没有左右节点。因此,当count(left)被调用的参数为NULL时,它将返回0,并且count(right)也会发生同样的情况。所以count(Node1)的表达式变成1 + 0 + 0。没有更多的计数函数被调用Node1,因此它返回到它的原始调用者,这是返回语句count(Node0)

由于我们有count(Node1)想通了,我们用count(Node0)的返回语句替换它。现在变成1 + (1 + 0 + 0) + count(Node2)

现在我打算让这个更快一点。由于Node2有两个子节点,Node2的return语句将为1 + count(Node3) + count(Node4)。就像Node1,count(Node3)count(Node4)将分别返回1 + 0 + 0,将count(Node2)的返回语句变为1 + (1 + 0 + 0) + (1 + 0 + 0)

现在count(Node2)已完全计算,让我们回归到count(Node2)原始调用者,这是1 + (1 + 0 + 0) + count(Node2)。替换我们从count(Node2)那里得到的,我们得到1 + (1+0+0) + (1 + (1+0+0) + (1+0+0))。把它加起来,我们得到5的值。 将此值返回到称为count(Node0)的任何函数,如语句int node_count = count(Node0)node_count将具有值5

+0

我认为我的递归概念并不好。但是在这个递归调用计数中(t-> left)继续调用自身,并且在左节点的地址被传递的情况下仅继续左节点,并且最终找到空值,它返回零来进行计数(t-> left)。 “有一个NULL值,它如何返回来计算正确的节点。请回复。 – srbh 2011-05-05 10:56:55

+0

我已经添加了一些细节。 – 2011-05-07 20:26:51

0

考虑这些树:

树没有节点(即一个NULL指针) - 返回0

与一个节点,根树。这将调用:

i=1+count(t->left)+count(t->right); 

与左,右NULL,因此将返回1 + 0 + 0

一棵树,根和一个右叶

i=1+count(t->left)+count(t->right); 

将返回1 (根据上述规则)的树根为0,树根为1的根(按上述规则),即1 + 0 + 1

依此类推。