I have a balanced binary search tree of integers and I want to find the leftmost node which stores the integer greater or equal to a fixed number like a using a function like ask(a).
for example suppose that I have added the following points in my tree, 8,10,3,6,1,4,7,14,13
Then the tree would be like this:
now ask(1) should be 1, ask(3) should be 3, ask(2) should be 3 and so on.
I think that I can use Inorder traversal to write my ask function, But I don't know how.
Iv written this piece of code so far:
inorderFind(node->left, a);
if (node->key.getX() >= a)
return node;
inorderFind(node->right, a);
The first argument is the current tree node and a is the a that is described above. I know that I can use a bool variable like flag and set it to true when the if condition holds, and then it would prevent from walking through other nodes of the tree and returning a false node. Is there anything else that I can do?
Trees have the wonderful property of allowing queries through simple, recursive algorithms. So, let's try to find a recursive formulation of your query.
Say LEFTMOST(u) is a function which answers this question :
Given the binary search subtree rooted at node u, with(possibly null) left and
right children l and r, respectively, what is the left-most node
with a value >= a?
The relation is quite simple:
LEFTMOST(u) = LEFTMOST(l) if it exists
LEFTMOST(r) otherwise
That's it. How you translate this to your problem and how you handle concepts like "null" and "does not exist" is a function of your representation.
Related
I want to write a function to check if two binary trees are the same.
The code looks like:
bool checkSame(Node* first, Node* second) {
// Check if nodes are the same
// Check left nodes: checkSame(first->left, second->left)
// Check right nodes: checkSame(first->right, second->right)
}
The issue is that I'm not sure what to return here. All the implementations of DFS I've found have a void return value. Is there one where it returns a bool?
Also, I'm looking for a recursive solution, not an iterative one.
You do it in exactly the same way as if you were calling some other functions instead of recursing.
(Recursion's big secret is that there's nothing special about recursion.)
The trees are equal if and only if
the nodes are equal, and
both its subtrees are equal
so
return first->data == second->data
&& checkSame(first->left, second->left)
&& checkSame(first->right, second->right);
Handling the empty cases left as an exercise.
I use the following method to traverse* a binary tree of 300 000 levels:
Node* find(int v){
if(value==v)
return this;
else if(right && value<v)
return right->find(v);
else if(left && value>v)
return left->find(v);
}
However I get a segmentation fault due to stack overflow.
Any ideas on how to traverse the deep tree without the overhead of recursive function calls?
*
By "traverse" I mean "search for a node with given value", not full tree traversal.
Yes! For a 300 000 level tree avoid recursion. Traverse your tree and find the value iteratively using a loop.
Binary Search Tree representation
25 // Level 1
20 36 // Level 2
10 22 30 40 // Level 3
.. .. .. .. .. .. ..
.. .. .. .. .. .. .. .. // Level n
Just to clarify the problem further. Your tree has a depth of n = 300.000 levels. Thus, in the worst case scenario a Binary Search Tree (BST) will have to visit ALL of the tree's nodes. This is bad news because that worst case has an algorithmic O(n) time complexity. Such a tree can have:
2ˆ300.000 nodes = 9.9701e+90308 nodes (approximately).
9.9701e+90308 nodes is an exponentially massive number of nodes to visit. With these numbers it becomes so clear why the call stack overflows.
Solution (iterative way):
I'm assuming your Node class/struct declaration is a classic standard integer BST one. Then you could adapt it and it will work:
struct Node {
int data;
Node* right;
Node* left;
};
Node* find(int v) {
Node* temp = root; // temp Node* value copy to not mess up tree structure by changing the root
while (temp != nullptr) {
if (temp->data == v) {
return temp;
}
if (v > temp->data) {
temp = temp->right;
}
else {
temp = temp->left;
}
}
return nullptr;
}
Taking this iterative approach avoids recursion, hence saving you the hassle of having to recursively find the value in a tree so large with your program call stack.
A simple loop where you have a variable of type Node* which you set to the next node, then loop again ...
Don't forget the case that the value you are searching for does not exist!
You could implement the recursion by not using the call stack but a user-defined stack or something similar; this could be done via the existing stack template. The approach would be to have a while loop which iterates until the stack is empty; as the existing implementaion uses depth-first search, elimination of the recursive calls can be found here.
When the tree that you have is a Binary Search Tree, and all you want to do is search for a node in it that has a specific value, then things are simple: no recursion is necessary, you can do it using a simple loop as others have pointed out.
In the more general case of having a tree which is not necessarily a Binary Search Tree, and wanting to perform a full traversal of it, the simplest way is using recursion, but as you already understand, if the tree is very deep, then recursion will not work.
So, in order to avoid recursion, you have to implement a stack on the C++ heap. You need to declare a new StackElement class that will contain one member for each local variable that your original recursive function had, and one member for each parameter that your original recursive function accepted. (You might be able to get away with fewer member variables, you can worry about that after you have gotten your code to work.)
You can store instances of StackElement in a stack collection, or you can simply have each one of them contain a pointer to its parent, thus fully implementing the stack by yourself.
So, instead of your function recursively calling itself, it will simply consist of a loop. Your function enters the loop with the current StackElement being initialized with information about the root node of your tree. Its parent pointer will be null, which is another way of saying that the stack will be empty.
In every place where the recursive version of your function was calling itself, your new function will be allocating a new instance of StackElement, initializing it, and repeating the loop using this new instance as the current element.
In every place where the recursive version of your function was returning, your new function will be releasing the current StackElement, popping the one that was sitting on the top of the stack, making it the new current element, and repeating the loop.
When you find the node you were looking for, you simply break from the loop.
Alternatively, if the node of your existing tree supports a) a link to its "parent" node and b) user data (where you can store a "visited" flag) then you don't need to implement your own stack, you can just traverse the tree in-place: in each iteration of your loop you first check if the current node is the node you were looking for; if not, then you enumerate through children until you find one which has not been visited yet, and then you visit it; when you reach a leaf, or a node whose children have all been visited, then you back-track by following the link to the parent. Also, if you have the freedom to destroy the tree as you are traversing it, then you do not even need the concept of "user data": once you are done with a child node, you free it and make it null.
Well, it can be made tail recursive at the cost of a single additional local variable and a few comparisons:
Node* find(int v){
if(value==v)
return this;
else if(!right && value<v)
return NULL;
else if(!left && value>v)
return NULL;
else {
Node *tmp = NULL;
if(value<v)
tmp = right;
else if(value>v)
tmp = left;
return tmp->find(v);
}
}
Walking through a binary tree is a recursive process, where you'll keep walking until you find that the node you're at currently points nowhere.
It is that you need an appropriate base condition. Something which looks like:
if (treeNode == NULL)
return NULL;
In general, traversing a tree is accomplished this way (in C):
void traverse(treeNode *pTree){
if (pTree==0)
return;
printf("%d\n",pTree->nodeData);
traverse(pTree->leftChild);
traverse(pTree->rightChild);
}
I have a function that is supposed to tell whether a given binary tree A is contained by a given binary tree B. The function defines "contained" as "A is covered by B, or any complete subtree of B." If, for instance, tree A is an empty tree and tree B is not, would A therefore be contained in B? What about if they're both empty?
Thanks!
In mathematic sense empty set (tree is just specialization of set) is contained in every other set including other empty set.
So yes on both your questions.
Empty set has even its wiki: http://en.wikipedia.org/wiki/Empty_set
Anyway it will become obvious from your implementation that the empty tree is contained in every other tree, an example implementation will look like this:
bool Tree::contains(const Tree& otherTree)
{
for (n: otherTree)
{
if (!contains(n))
return false;
}
return true;
}
Of course I can imagine better implementation especially when trees are sorted - but the point is that if for(n: otherTree) will cause no iterations then the result is true.
I was going through the tutorial of binary tree .
And I am slightly stuck in use of recursive function . say for example I need to count no of nodes in a tree
int countNodes( TreeNode *root )
{
// Count the nodes in the binary tree to which
// root points, and return the answer.
if ( root == NULL )
return 0; // The tree is empty. It contains no nodes.
else
{
int count = 1; // Start by counting the root.
count += countNodes(root->left); // Add the number of nodes
// in the left subtree.
count += countNodes(root->right); // Add the number of nodes
// in the right subtree.
return count; // Return the total.
}
} // end countNodes()
Now my doubt is-> how would it count say root->left->left of right ? or root->right->left->left??
Thanks
With recursive functions, you should think recursively! Here's how I would think of this function:
I start writing the signature of the function, that is
int countNodes( TreeNode *root )
So first, the cases that are not recursive. For example, if the given tree is NULL, then there are no nodes, so I return 0.
Then, I observe that the number of nodes in my tree are the number of nodes of the left sub-tree plus the number of nodes of the right sub-tree plus 1 (the root node). Therefore, I basically call the function for the left and right nodes and add the values adding 1 also.
Note that I assume the function already works correctly!
Why did I do this? Simple, the function is supposed to work on any binary tree right? Well, the left sub-tree of the root node, is in fact a binary tree! The right sub-tree also is a binary tree. So, I can safely assume with the same countNodes functions I can count the nodes of those trees. Once I have them, I just add left+right+1 and I get my result.
How does the recursive function really work? You could use a pen and paper to follow the algorithm, but in short it is something like this:
Let's say you call the function with this tree:
a
/ \
b c
/ \
d e
You see the root is not null, so you call the function for the left sub-tree:
b
and later the right sub-tree
c
/ \
d e
Before calling the right sub-tree though, the left sub-tree needs to be evaluated.
So, you are in the call of the function with input:
b
You see that the root is not null, so you call the function for the left sub-tree:
NULL
which returns 0, and the right sub-tree:
NULL
which also returns 0. You compute the number of nodes of the tree and it is 0+0+1 = 1.
Now, you got 1 for the left sub-tree of the original tree which was
b
and the function gets called for
c
/ \
d e
Here, you call the function again for the left sub-tree
d
which similar to the case of b returns 1, and then the right sub-tree
e
which also returns 1 and you evaluate the number of nodes in the tree as 1+1+1 = 3.
Now, you return the first call of the function and you evaluate the number of nodes in the tree as 1+3+1 = 5.
So as you can see, for each left and right, you call the function again, and if they had left or right children, the function gets called again and again and each time it goes deeper in the tree. Therefore, root->left->left or root->right->left->left get evaluated not directly, but after subsequent calls.
That's basically what the recursion's doing, it's adding 1 each time countNodes is called as it gets to a child node (int count = 1;) and terminating when it tries to go to the next child of a leaf node (since a leaf has no children). Each node recursively calls countNodes for each of it's left and right children and the count slowly increases and bubbles to the top.
Try and look at it this way, where 1 is added for each node and 0 for a non-existing node where the recursion stops:
1
/ \
1 1
/ \ / \
1 0 0 0
/ \
0 0
The 1's each add up, with the node's parent (the calling function at each level of recursion) adding 1 + left_size + right_size and returning that result. Therefore the values returned at each stage would be:
4
/ \
2 1
/ \ / \
1 0 0 0
/ \
0 0
I'm not sure that made it any clearer but I hope it did.
Say you call countNodes(myTree);. Assuming myTree is not null, countNodes will eventually execute count += countNodes(root->left);, where root is myTree. It re-enters your countNodes function with the entire tree rooted at root->left (which is myTree->left). The logic then repeats itself; if there is no root->left, then the function returns 0. Otherwise, it will eventually call count += countNodes(root->left); again, but this time root will actually be myTree->left. That way it will count myTree->left->left. Later it does the same thing with the right nodes.
That's the beauty of recursive algorithms. The function is defined over the current node and its children. You only have to convince yourself that the current invocation is correct as long as the recursive calls to the left and right children are correct. Exactly the same reasoning applies to the children and their children, and so on ... it'll all just work.
It will start by root->left->(subnode->left) etc. until that branch returns 0 e.g. if it is not an actual node (a leaf in the tree);
Then the deepest node will check for root->right and repeat the same procedure. Try to visualize this with a small tree :
So in this case your function will go A->D->B then the right nodes will all return 0 and you will get a last +1 from your C node.
The algorithm implementation you write is exhaustive. It visit the entire tree.
If the tree is empty, count is zero.
If not, we get the left node, let's call it L and we add 1 to our count.
Since it is proven that a subtree of a tree is itself a tree, we perform the same algorithm again on the tree that have L as root.
We now do it for the tree that have the root right node as root.
Now... this indeed works.
A subtree of a tree is a tree, also for empty or single nodes.
You should look at the definition of tree.
You can prove it using Mathematical Induction and formulate your problem in terms of inductive reasoning.
Recursive algorithms uses often a structure very similar to inductive reasoning.
The trick with recursive functions is that there is a base case and an inductive step, just like mathematical induction.
The base case is how your recursive algorithm knows to stop. In this case it is if (root == NULL) -- this node doesn't represent a tree. This line is executed on every single node in your binary tree, even though it calls each one root at the time. It is false for all the nodes of the tree, but when you begin calling the recursive routine on the children of the leaf nodes -- which are all NULL -- then it will return 0 as the count of nodes.
The inductive step is how your recursive algorithm moves from one solved state to the next unsolved state by converting the unsolved problem into (one or more) already-solved problems. Your algorithm needs to count the number of nodes in a tree; you need 1 for the current node, and then you have two simpler problems -- the number of nodes in the tree on the left, and the number of nodes on the tree on the right. Get both of those, add them together, add the 1 for the current node, and return that as the count of nodes in this tree.
This concept really is fundamental to many algorithms in computer science, so it is well worth studying it until you fully understand it. See also quicksort, Fibonocci sequence.
Think that the program goes first at the deepest branches. Then it goes backwards returning the count number to its previous member.
A
/ \
B C
/ \ \
D E F
So first the program runs until
count += countNodes(root->left);
It pauses what it's done so far(aparently nothing special) and goes into B. Same happens there and it goes to D. At D it does the same. However here we have a special case. The program sees at the beginning at line
if ( root == NULL )
that the nonexistent left child of D is indeed NULL. Therefore you get back 0.
Then we go back at where we paused last time and we continue like this. Last time we were at B so we continue past the line
count += countNodes(root->left);
and run the next line
count += countNodes(root->right);
This goes on until you get back to A. But at point A again we had paused just after searching the left leave of A. Therefore we continue with the right leave. Once we are done going through whola that branch we get back to A.
At this point we don't have any unfinished business(pauses) left so we just return the count that we gathered through whole this process.
Every subtree has its own root, just as the actual tree has a root. The counting is the same as for each of the subtrees. So you just keep going until you reach the leaf nodes and stop that local recursion, returning and adding up the nodes as you go.
Draw the entire tree, then assign 1 for all leafs nodes (leaf nodes are at level N). After that you should be able to calculate the number of nodes that is generated by each node on a higher level (N-1) just by summing: 1 + 1 if the node has two children or 1 if the node has only one child. So for each node on level N-1, assign the value 1 + sum(left,right). Following this you should be able to calculate the number of nodes of the entire tree. The recursion that you posted, do just that.
http://www.jargon.net/jargonfile/r/recursion.html
UPDATE:
The point is that both the data structure and the program are recursive.
for the data structure this means: a subtree is also a tree.
for the code it means: counting the tree := counting the subtrees (and add one)
I am trying to preorder a BST
I am not sure how to do it.
You should consider a recursive approach rather than an iterative one. Tree traversal (preorder, inorder, and postorder) is very easily done using recursion.
The Wikipedia article on tree traversal has a pseudocode recursive algorithm, but there's really not much to it. Since you're storing the tree in an array, you won't have node pointers, just indices.
As for how you know when you reach the leaf nodes, well, their indices will be beyond the end of the array.
Doing a tree traversal is usually done with recursive functions because that is the most natural way to express the traversal.
Doing a pre-order traversal is pretty easy. Ignoring the details, you have something like this:
void do_preorder(Tree t)
{
// do something with the current tree node
if (leftnode(t) not empty)
do_preorder(leftnode(t));
if (rightnode(t) not empty)
do_preorder(rightnode(t))
}
If you want to be tricky, you can even create a generic traversal that allows you to choose the flavor (pre-order, in-order or post-order) at runtime:
void do_xorder(Tree t, Flavor f)
{
if (f == PREORDER)
handle_currentnode(t)
if (leftnode(t) not empty)
do_xorder(leftnode(t), f);
if (f == INORDER)
handle_currentnode(t)
if (rightnode(t) not empty)
do_xorder(rightnode(t), f)
if (f == POSTORDER)
handle_currentnode(t)
}
As per you code you can use (2i + 1) for left and (2i + 2) for right child.
My suggestion that you should start storing elements from index 1 in the array because you can store left child at ( 2 * i) index and right child at (2*i + 1) index .
And end of the left child can be easily found by checking whether ( 2*i > currSize ) is true.
http://en.wikipedia.org/wiki/Tree_traversal
Check out this link for any traversal you want to perform on tree...