maximum depth for a binary tree - recursion

Could someone explain the maxDepth() function, what value is being returned to ldepth and rdepth. How do the values increase for ldepth and rdepth with each recursion, I want to know which values are they storing. ldepth and rdepth were not even initialized with initial values. Do the values increment with every recursive process? I basically want to know the following two steps ldepth=maxDepth(node->left)); and rdepth=maxDepth(node->right));
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *left;
struct node *right;
};
int maxDepth(struct node *node)
{
if(node==NULL)
return 0;
else
{
int ldepth;
int rdepth;
ldepth=maxDepth(node->left));
rdepth=maxDepth(node->right));
if(ldepth>rdepth)
return (ldepth+1);
else return (rdepth+1);
}
}
struct node* newNode(int data)
{
struct node* node=(struct node*)malloc(sizeof(struct node));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
int main()
{
struct node *root=newNode(1);
root->left=newNode(2);
root->right=newNode(3);
root->left->left=newNode(4);
root->left->right=newNode(5);
printf("Height of tree is %d",maxDepth(root));
getchar();
return 0;
}

Do the values increment with every recursive process?
Not exactly. The recursion goes deeper as long as there are child nodes. Once it satisfies 'if(node==NULL)', that is, there are no more leafs, it will return 0 to the calling node. Only then the value is incremented where it reaches 'return (ldepth+1);'

max depth takes root.
root is node, its value is 1.
As a node it has a left and a right node.
the left node of root has also a left and a right node.
so the tree looks like:
1 -> 2 -> 4
| | -> 5
|--> 3
maxDepth takes the element 1
it looks if the parameter is null, since 1 is not null it calls max depth for the left node 2 and the right node 3
lets focus on 2 now
2 is not null so it calls max depth for 4 and 5
lets focus on 4 now
4 is not null so it will call maxdepth for 4's left and right
4's left is NULL so it will return the value 0
now the function that calls the recursion continues (the maxDepth(4))
the value of ldepth is now 0
its increased by one and we fall back to the caller function maxDepth(2)
the depth is increased by 1
etc.
at the end we have the result.

Related

Size of Binary Tree: wrong result when submitting code to online judge

I was trying to solve GeeksForGeeks problem Size of Binary Tree:
Given a binary tree of size N, you have to count number of nodes in it. For example, count of nodes in below tree is 4.
1
/ \
10 39
/
5
Unfortunately for the test case below I'm getting "incorrect answer" on my recursive code. Can someone tell me where I'm going wrong?
Input:
2 // Number of test cases
1 2 3 // Test Case #1
10 5 9 N 1 3 6 // Test Case #2
My Output:
3
9
Expected Output:
3
6
My Code:
/* Tree node structure used in the program
struct Node
{
int data;
Node* left;
Node* right;
}; */
/* Computes the number of nodes in a tree. */
int nodes=0;
void dfs(Node* node) {
if (node==NULL) return;
++nodes;
// cout << node->data << " ";
dfs(node->left);
dfs(node->right);
}
int getSize(Node* node)
{
// Your code here
dfs(node);
return nodes;
}
The mistake is that your code has a global int nodes that is only initialised once. When getSize is called multiple times, then only at the first call you can be sure it really is zero. All other calls will just keep incrementing that counter without it having been reset.
So either reset that counter just before the call to dfs is made, or -- better -- redesign your code so that you don't need a global counter at all, for example by having dfs return a counter. And if you do that, you can even make getSize recursive itself, without any need of a separate dfs function.
NB: don't use NULL in C++, but nullptr.
Here is a spoiler solution:
int getSize(Node* node) {
if (node==nullptr) return 0;
return 1 + getSize(node->left) + getSize(node->right);
}

Checking whether two lists are similar or not

In one of the examination, they asked us to write a function "int similar()"
to check whether two list's data are similar or not irrespective of their order. they can also be of different sizes(in that case, they are dissimilar)
that is,. 3->2->-1 and -1>3>2 are similar
I wrote a program for that which is shown below.
that is, for list one,I am adding all the elements and storing in sum1.
I am multiplying all the elements and storing in product1.
similarly , sum2 and product2 for 2nd list.
if their sums and products are equal, then they must be containing same elements.
my question is that is this algorithm complete?
is there any case where my logic fails?
please help me
#include<stdio.h>
struct _node_
{
int data;
struct _node_ *ptr;
};
typedef struct _node_ Node;
struct _linkedlist_
{
Node *head;
Node *tail;
int count;
};
typedef struct _linkedlist_ List;
int similar(List *, List *);
int main()
{
//...code//
return 0;
}
int similar(List *one, List *two)
{
int sum1=0;
int sum2=0;
int product1=1;
int product2=1;
int i;
Node *temp;
temp=one->head;
for(i=0;i<one->count;i++)
{
sum1=sum1+(temp->data);
prodcut1=product1*(temp->data);
temp=temp->ptr;
}
temp=two->head;
for(i=0;i<two->count;i++)
{
sum2=sum2+(temp->data);
prodcut2=product2*(temp->data);
temp=temp->ptr;
}
if(sum1==sum2 && product1==product2)
return 1;
return0;
}
Your algorithm is not complete since your logic can fail. For your example 3->2->-1 there is another sequence that has the same sum and product but is not similar, namely
1 -> (3 + sqrt(33)) / 2 -> (3 - sqrt(33)) / 2
(Those values round to 1, 4.37228, and -1.37228.)
You can check and see that the sum of those values is 4 and the product is -6, just like your original list.
This happens because you put only two requirements on the values, which means you remove only two degrees of freedom. If the list has three or more values, that leaves one or more degrees of freedom, which allows for infinitely many possibilities. I showed you an example where the first value was 1--an example could be given for any value x where it is not true that -0.971168 < x <= 0 (approximately).
So you need another approach. You could sort each list then compare them. You could also put the values for each list into a multi-set (also called a bag or mset or counter) and compare those multi-sets.
As per the requirement mentioned in the question of the data being similar (i.e you are only checking for the order of data)
Consider a case where you have elements [-3,0,3] in list 1 and elements [10,-10,0] in the list 2.
In this case, the sum will be 0, and the product will also be 0
1. Sort both lists
2. Check every item of the list.
2.1 if they are not equal
-> print: lists are not equal.
3. lists are equal
Note: you either can sort the list, or make two separate lists, adding values in sorted order.

Keeping count in non-tail recursion

I am writing several recursive functions in a functional language(ML), and in several of them it is necessary to keep count. I am not allowed to use tail recursion, or helper functions. How should I keep count?
For example if one problem calls for me to remove the nth element of a string, how can I know the recursive function has been called n times, before dropping that element?
You can pass the count as a parameter. I don't know ML, but in C-style languages it's done like so:
void processTreeNode(Node* node, int count) {
foreach(Node* child in node->children) {
processTreeNode( child, count + 1 );
}
}
The first call usually has a value of 0 or 1:
Node* root = ...
processTreeNode( root, 1 );
Note the above example actually counts depth rather than iteration count.
If you want to count the number of times the function has actually been called, you can use either a value in global state (a bad idea) or a thread-local value passed by reference:
void processTreeNode(Node* node, int* count) {
(*count)++;
foreach(Node* child in node->children) {
processTreeNode( child, count );
}
}
With the first call responsible for creating the value and reference:
Node* root = ...
int count = 0;
processTreeNode( root, &count );
This can be generalised to an algorithm "context" object which is passed to all function calls - if it's passed by-reference then this avoids needless value-copying and stack space allocations, as well as being thread-safe provided no other thread has access to it:
class MyAlgorithmContext {
int foo;
string bar;
}
Node* root = ...
MyAlgorithmContext context;
context.foo = 123;
processTreeNode( root, &context );

Printing the words of a trie tree

I was trying to print the contents of a trie in C. However I'm not very sucessful. And also let me say right in the beginning that this something we are doing in school right now, and this is one exercise.
This is how my trie looks like:
struct node{
char letter; //holds the letter associated with that node
int count; //its count
struct node* child[26]; //each node can have 26 children
};
struct trie{
struct node* root;
};
This print method has to traverse this trie and print the words in alphabetic order and the ones that have a count of 0 should not be printed.
I was thinking along recursion and this is what my code looks like:
void print(node* root) {
char buffer[15];//array to store the letters
if(root==NULL){ return;}//if the root is null return
int i;
int index=0; //index for the buffer
int hasAChild=hasChild(root);
if (hasAChild != 0) { //the root has children keep on going
for (i=0;i<27;i++) {
//go thru all the children and if they have children call print recursively
if (hasChild(root->child[i])) {
print(root->child[i]);
}
else {
// if they have no more children add the letter to the buffer
buffer[index++] = root->child[i]->letter;
}
// print the contents in the bufffer
printf("%s: %d",root->child[i]->count);
}
}
}
// function to determine if a node has children, if so it returns their number if not,returns 0
int hasChild(root) {
if(root==NULL){
return 0;
}
int i;
int count=0;
for(i=0;i<27;i++){
if(root->child[i]!=NULL){
count++;
}
}
return count;
}
This is what it would look like
Example of a trie:
Root
+--- a:2
| +--- t:4
|
+--- b:3
| +--- e:5
|
+--- c:0
we have 'a' 2 times, 'at' 4 times, 'b' 3 times and 'be' 5 times, only the words should be printed.
In this example I will have to print
at: 4
be: 5
but not c: 0 since its count is 0
So i'm only suppose to print the words that are formed, not the letters that do not form a word. Any help or guidance would be greatly appreciated. Thank you!
I see three issues here:
you append a letter to the current buffer only when the current node has no children. This means that you will only display the last letter of the words.
in addition, every time you enter the function, you start with an empty buffer.
your printf statement is missing a string argument.
You need to pass the length and the buffer, and make sure to null-terminate it correctly.

Recursively reverse a linkedlist (code in Stanford CSed library) explanation

My recursion skill is pretty rusty. I've been thinking about this problem and searched the forum for a long time but still cannot understand. Right now I'm looking at the recursively reverse a linked list code from Stanford CS ed library.
#include <stdio.h>
struct Node {
int x;
struct Node *next;
};
void Reverse(struct Node ** headRef){
struct Node* first;
struct Node* rest;
if(*headRef==NULL)
return;
first= *headRef;
rest= first->next;
if(rest==NULL)
return;
Reverse(&rest);
printf("Rest%d\n", (rest)->x); // I added this line to print rest
first->next->next=first;
first->next=NULL;
*headRef=rest;
}
void printList(struct Node* head){
if(!head)
return;
else{
printf("%d ", head->x);
printList(head->next);
}
}
void main(){
struct Node *head;
struct Node * node1= (struct Node*) malloc(sizeof(struct Node));
struct Node * node2= (struct Node*) malloc(sizeof(struct Node));
struct Node * node3= (struct Node*) malloc(sizeof(struct Node));
struct Node * node4= (struct Node*) malloc(sizeof(struct Node));
head= node1;
node1->next=node2;
node1->x=1;
node2->x=2;
node3->x=3;
node4->x=4;
node2->next=node3;
node3->next=node4;
node4->next=NULL;
Reverse(&head);
}
Now suppose I have a linked list 1->2->3->4. What I cannot understand is the last line, which will set the headRef to 4 eventually, I think it should set the headRef to 2. I tried to execute the function and it printed out:
4
4
4
for the variable rest.
However, if I commented the last line in the the Reverse function out, it still reversed the list but would print
4
3
2.
The second result I can understand, but the first one seemed quite confusing. Does the statement "*headRef=rest" do any thing to the variable rest? What does it keep pointing to 4?
Also, if I pass *headRef instead of **headRef (last line is not commented out), it would print the result
4
3
2
too.
Could anyone please explain to me what happened in the memory? Thanks a million.
Before the recursive call to Reverse we have:
first---|
|
v
1->2->3->4->NULL
^
|
|
rest------
After the recursive call to Reverse we have:
first---|
|
v
1->2<-3<-4
| ^
v |
NULL |
rest------------
Now we need to fix 2->NULL to 2->1 by first->next->next=first.
first---|
|
v
1<-2<-3<-4
| ^ ^
|--| |
|
rest------------
Now we need to fix 1->2 to 1->NULL by first->next=NULL.
first---|
|
v
NULL<-1<-2<-3<-4
^
|
|
rest------------
Finally *headRef=rest so that *headRef will point to 4 instead of to 1.
What happens here is as because the recursive call passes the address of rest to the local variable headRef, when each recursive call returns, the statement *headRef=rest already changes the address of rest pointer for the statements coming next in the execution flow.
For the linked list 1->2->3->4 :
Let us assume 1 is stored in address 100, 2 in address 200, 3 in address 300 and 4 in address 400.
PART 1:
the call Reverse(&rest) [rest points to address 400]
first = 400
rest = NULL
as rest is NULL the execution returns to the point after Reverse(400) call
PART 2:
Here first = 300 and rest = 400
after execution of first->next->next=first and first->next=NULL
we have *headRef=rest [rest points to 400]
but this headRef was passed an address of rest=300. So now already for the next step in execution,
rest points to 400.
PART 3:
Now execution returns to the point after Reverse(300) call
But during forward call [first was 200 and rest was 300] and during return [rest = 400]. HERE'S THE TRICK!!!
after execution of first->next->next=first and first->next=NULL
we have *headRef=rest [rest points to 400]
but this headRef was passed an address of rest=200. So now already for the next step in execution,
rest points to 400.
PART 4:
Now execution returns to the point after Reverse(200) call
But during forward call [first was 100 and rest was 200] and during return [rest = 400].
after execution of first->next->next=first and first->next=NULL
we have *headRef=rest [rest points to 400]
and as because this is the initial call, the function returns with *headRef having 400 value.
JOB DONE!

Resources