Following are 2 codes:
1. Find the kth smallest integer in a binary search tree:
void FindKthSmallest(struct TreeNode* root, int& k)
{
if (root == NULL) return;
if (k == 0) return; // k==0 means target node has been found
FindKthSmallest (root->left, k);
if (k > 0) // k==0 means target node has been found
{
k--;
if (k == 0) { // target node is current node
cout << root->data;
return;
} else {
FindKthSmallest (root->right, k);
}
}
}
Find the number of nodes in a binary tree:
int Size (struct TreeNode* root)
{
if (root == NULL) return 0;
int l = Size (root->left);
int r = Size (root->right);
return (l+r+1);
}
My Question:
In both these codes, I will have to keep track of the number of nodes I visit. Why is it that code 1 requires passing a parameter by reference to keep track of the number of nodes I visit, whereas code 2 does not require any variable to be passed by reference ?
The first code (1) is looking for the smallest node in your BST. You search from the root down the left side of the tree since the smallest valued node will be found in that location. You make several checks:
root == null - to determine if the tree is empty.
k == 0 - zero in this case is the smallest element. You are making this assumption based on whatever principles are apart of this tree.
Then you recursively traverse the list to find the next smallest in the left side of the tree. You perform one more check that if k > 0 you decrement k <- this is why you need to pass by reference since you are making changes to some value k given by a separate function, global variable, etc. If k happens to be zero then you have found the smallest valued node, if not you go one right of the current node and then continue the process from there. This seems like a very arbitrary way of finding the smallest node...
For the second code (2) you are just counting the nodes in your tree starting at the root and counting each subsequent node (either left or right) recursively until no more nodes can be found. You return your result which is the total amount of left nodes,right nodes. and + 1 for the root since it was not counted earlier. In this instance no passed by reference variable is needed although you could potentially implement one if you choose to do so.
Does this help?
Passing the parameter by reference allows you to keep track of the count within the recursive process, otherwise the count would reset. It allows you to modify the data within the memory space, thus changing the former value not the current/local value.
Related
I have to check if this is BST or not i have implemented recursion and it is giving run time error for the tree level order 2 N 7 N 6 N 5 N 9 N 2 N 6
bool isBST(Node* root)
{
if(root==NULL)
return 1;
if(root->left==NULL && root->right==NULL)
return 1;
if((root->data)<(root->left->data))
return 0;
if( (root->data)>(root->right->data))
return 0;
if(root->right==NULL)
return isBST(root->left);
if(root->left==NULL)
return isBST(root->right);
if(!isBST(root->left) || !isBST(root->right))
{
return 0;
}
return 1;
}
Your code may dereference a null pointer. For instance, if root has a right child, but not a left child, then this code will be executed which performs an invalid dereference:
if((root->data)<(root->left->data))
But even if you add the necessary checks to avoid such invalid dereferencing, the algorithm is not correct.
It is not true that the following conditions define a valid BST:
The left child of a node is either null or has a value that is not greater than the node's own value, AND
The right child of a node is either null or has a value that is not less than the node's own value, AND
The above is also true for the left and right child (recursive step)
For instance, this would all be true for this tree:
5
/ \
2 8
\
7
... but this tree is not a valid BST, because 7 is greater than 5, which is not allowed. All values in the left subtree of a node must not be greater than the node's own value. Your code only checks this for the direct child, but it should make sure that this is also true for any other descendants in that left subtree.
The common way to make a correct verification, is to pass to the recursive call a window (minimum and maximum) of values which the subtree may contain.
So I have a problem and I have the Algorithm for it, but I just can't seem to be able to turn it into code in C.
Problem: Given an AVL tree, return the next minimum natural value that's not in the tree.
Example: if 2 is the minimum in the tree, I should find out whether or not 3 is one of the nodes in the tree, if it is not, I should return the value 3, if it is, I should see if 4 is in the tree, and so on...
Algorithm to the problem that works in O(logn) (when n is the Number of nodes found in the tree):
first, we check if node->size = node -> key - TreeMinimum
if yes, go to the right side of the tree.
if no, then go to the left.
when we reach NULL, we should return the value of the last node we visited plus 1.
SIZE of the node is the number of nodes that are under this node, including the node itself.
I wrote this code in c but it doesn't seem to work :
int next_missing( AVLNodePtr tnode )
{
int x,y;
if(tnode==NULL)
{
return (tnode->key)+1;
}
if(tnode->size == tnode->key - FindMin(tnode))
x = next_missing(tnode->child[1]);
if(tnode->size != tnode->key - FindMin(tnode))
y = next_missing(tnode->child[0]);
if(x>y) return y;
else return x;
}
Any help/tips on how to fix the code would be appreciated.
Thanks.
Maybe this question does not belong as this is not a programming question per se, and i do apologize if this is the case.
I just had an exam in abstract data structures, and there was this question:
the rank of a tree node is defined like this: if you are the root of the tree, your rank is 0. Otherwise, your rank is the rank of your parents + 1.
Design an algorithm that calculates the sum of the ranks of all nodes in a binary tree. What is the runtime of your algorithm?
My answer I believe solves this question, my psuedo-code is as such:
int sum_of_tree_ranks(tree node x)
{
if x is a leaf return rank(x)
else, return sum_of_tree_ranks(x->left_child)+sum_of_tree_ranks(x->right_child)+rank(x)
}
where the function rank is
int rank(tree node x)
{
if x->parent=null return 0
else return 1+rank(x->parent)
}
it's very simple, the sum of ranks of a tree is the sum of the left subtree+sum of the right subtree + rank of the root.
The runtime of this algorithm I believe is n^2. i believe this is the case because we were not given the binary tree is balanced. it could be that there are n numbers in the tree but also n different "levels", as in, the tree looks like a linked list rather than a tree. so to calculate the rank of a leaf, potentially we go n steps up. the father of the leaf will be n-1 steps up etc...so thats n+(n-1)+(n-2)+...+1+0=O(n^2)
My question is, is this correct? does my algorithm solve the problem? is my analysis of the runtime correct? and most importantly, is there a better solution to solve this, that does not run in n^2?
Your algorithm works. your analysis is correct. The problem can be solved in O(n) time: (take care of leaves by yourself)
int rank(tree node x, int r)
{
if x is a leaf return r
else
return rank(x->left_child, r + 1)+ ranks(x->right_child, r + 1) + r
}
rank(tree->root, 0)
You're right but there is an O(n) solution providing you can use a more "complex" data structure.
Let each node hold its rank and update the ranks whenever you add/remove, that way you can use the O(1) statement:
return 1 + node->left.rank + node->right.rank;
and do this for each node on the tree to achieve O(n).
A thumb rule for reducing Complexity time is: if you can complex the data structure and add features to adapt it to your problem, you can reduce Complexity time to O(n) most of the times.
It can be solved in O(n) time where n is number of Nodes in Binary tree .
It's nothing but sum of height of all nodes where height of root node is zero .
As
Algorithm:
Input binary tree with left and right child
sum=0;
output sum
PrintSumOfrank(root,sum):
if(root==NULL) return 0;
return PrintSumOfrank(root->lchild,sum+1)+PrintSumOfRank(root->Rchild,sum+1)+sum;
Edit:
This can be also solved using queue or level order of traversal tree.
Algorithm using Queue:
int sum=0;
int currentHeight=0;
Node *T;
Node *t1;
if(T!=NULL)
enque(T);
while(Q is not empty) begin
currentHeight:currentHeight+1 ;
for each nodes in Q do
t1 = deque();
if(t1->lchild!=NULL)begin
enque(t1->lchild);sum = sum+currentHeight;
end if
if(t1->rchild!=NULL)begin
enque(t1->rchild);sum = sum+currentHeight;
end if
end for
end while
print sum ;
Given a Binary Tree, find the maximum sum path from a leaf to root. For example, in the following tree, there are three leaf to root paths 8->-2->10, -4->-2->10 and 7->10. The sums of these three paths are 16, 4 and 17 respectively. The maximum of them is 17 and the path for maximum is 7->10.
10
/ \
-2 7
/ \
8 -4
This is a function to calculate maximum sum from root to any leaf node in the given binary tree. This problem is asked in interview many times by various companies. I am trying this declaring ls and rs as static, but it's producing wrong output. When I'm removing static keyword it's producing correct output.
Can you please explain me what is the problem here with the static keyword.
int roottoleafmaxsum(struct node*temp) //root will be passed as an argument
{
static int ls,rs; //left sum and right sum
if(temp) //if temp!=NULL then block will be executed
{
ls=roottoleafmaxsum(temp->left); //recursive call to left
rs=roottoleafmaxsum(temp->right); //recursive call to right
if(ls>rs)
return (ls+temp->data); //it will return sum of ls and data
else
return (rs+temp->data); //it will return sum of rs and data
}
}
Static means they will retain the value for every function call.
Since you are using recursion, it will change the value in the recursive call and that same value will be used in the parent function producing errors.
I was trying to understand program of recursion
Anyone Please explain working of size(). how it is returning no. of nodes recursively.
int size(struct tree *root)
{
if (root==NULL)
return 0;
else
{
return (size(root->left)+size(root->right)+1);
}
}:
In this program what does size(root->left),size(root->right) will return??
As in factorial program
function factorial (x)
{
return (x * factorial(x-1) ) ;
}
In this factorial program it will return 4*3*2*1.If we calculate for factorial(4).
In the above tree program what should return value of that node.Why it is returning no. of nodes?not the value of that node.
Please Explain.
The size function is calculating the number of nodes in the tree (completely independent of the values of the nodes). The recursion works because if the tree root is NULL it returns 0 (base case). If the root is not NULL, it has a left and right child (both of which are trees). So the total size will be size of left subtree (i.e. size(root->left)) + size of right subtree (i.e .size(root->right)) + size of root node (i.e. 1).
your program never is reading the value of node. instead is counting no. of nodes.
it returns 0 on reaching null. it adds 1 when all the nodes in right and left subtree are counted and returns the final sum.