简体   繁体   中英

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; 
}

Can someone explain to me how this works? Recursion is a bit confusing to me since I'm just starting. I understand that this +1 is for the root node but I don't understand how are r and l increasing.

Let's have a look at this simple tree:

  Root
 / \
A   B
   / \
  C   D

Then the calls and returns are as follows:

numOfNodes( Root )  
    numOfNodes(B)
        numOfNodes(D)
        return 1
        numOfNodes(C)
        return 1
    return 3    
    numOfNodes(A)
    return 1
return 5

Let's run to your code step by step with some example trees, getting more and more complex.

First example : empty tree

This is kind of an edge case. If the tree is empty, its root node is NULL you can see the function will immediately return 0, which is the correct result.

Second example : tree with one node

In this case our tree is just a single root node, let's call it "A". The structure of the tree looks like this:

     (A)
  /       \
NULL     NULL

We use NULL pointers as leaves to mark that the root node has no children. Let's proceed to the function call.

  • You call numOfNodes with A as its argument.
  • First we check that the argument is not NULL , this isn't the case so we continue.
  • Then we call numOfNodes with A->right as argument.
    • We enter another numOfNodes function, this time with rootNode = A->right
    • It turns out that A->right is NULL . So this call to numOfNodes doesn't go past the first if and returns 0.
  • We return to the initial call to numOfNodes , where r now has the value 0.
  • Then we call numOfNodes a third time, this time with rootNode = A->left as argument.
    • Similarly, this call to numOfNodes immediately returns 0 because A->left is NULL .
  • We return to the initial call to numOfNodes where l now has the value 0
  • We now can return the final result : the number of nodes on the left (0), the number of nodes on the right(0) plus the one we're currently at (1). Total r+l+1 = 1 , which is the correct result>

You may have noted that during the execution the function called another version of itself but with a different argument from the one it was initially called with. This idea is a very powerful programming technique called recursion , and is especially useful when dealing with trees.

In essence, you start with the root of the tree and ask it to count the number of node on its right, and the number of nodes on its left, then add one. To know the number of nodes on its right, is very simple. You use the same function as if the node on the right was the root of a new tree . This may lead to more and more calls to the same counting function, each time with a deeper node as the "fake root". The cascading calls stops when they reaches NULL node. Eventually the results "float back" up the tree as each function returns to the one that called it.

Third example : a more complete tree

Let's suppose we now have a binary tree with more nodes. Say we have this tree of height 3:

        __(A)__
     /          \ 
    (B)         (C)
   /   \       /   \
 NULL  (D)   NULL  NULL
      /   \             
    NULL  NULL
  • We begin by calling numOfNodes on the root of the tree, ie A . A is not NULL so we carry on.
  • We call numOfNodes with A->right as argument.
  • We thus enter another version (#2) of numOfNodes with A->right as argument. It turns out that A->right is C which is not NULL . This version of numOfNodes does not return 0 immediately.
  • We will enter a third version of numOfNodes , this time with C->right as argument.
  • It turns out that C->right is NULL so this version (#3) of numOfNodes returns 0
  • So the r variable in the second version of numOfNodes now has the value 0
  • The same thing happens when we compute the l variable because C->left is also NULL .
  • The second version of numOfNodes , the one called with C , reaches its final instruction and returns r+l+1 which is equal to 0+0+1=1 (0 nodes on the left, 0 nodes on the right, plus the "fake root" C).
  • We then return to the first numOfNodes , as we now know that r is 1.
  • We are now going to compute l for this version. For this we will call numOfNodes again, this times with A->left (ie B ) as argument.
  • I won't detail it (I encourage you to do it on paper), this time we will call numOfNodes four more times), and l is computed to be equal to 2 .
  • The total result is thus 4 (there's 1 node on the right, 2 on the left, plus the root node).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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