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.
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.
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.
numOfNodes
with A
as its argument.NULL
, this isn't the case so we continue.numOfNodes
with A->right
as argument.
numOfNodes
function, this time with rootNode = A->right
A->right
is NULL
. So this call to numOfNodes
doesn't go past the first if
and returns 0.numOfNodes
, where r
now has the value 0.numOfNodes
a third time, this time with rootNode = A->left
as argument.
numOfNodes
immediately returns 0 because A->left
is NULL
.numOfNodes
where l
now has the value 0r+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.
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
numOfNodes
on the root of the tree, ie A
. A
is not NULL
so we carry on. numOfNodes
with A->right
as argument.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.numOfNodes
, this time with C->right
as argument.C->right
is NULL
so this version (#3) of numOfNodes
returns 0r
variable in the second version of numOfNodes
now has the value 0l
variable because C->left
is also NULL
.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). numOfNodes
, as we now know that r
is 1.l
for this version. For this we will call numOfNodes
again, this times with A->left
(ie B
) as argument.numOfNodes
four more times), and l
is computed to be equal to 2
.
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.