i need to fill up this visitor class so it can be used to fill nodes with depth in a single pass
Example:
Consider the tree as
12
/ \
30 50
/ \ /
40 50 60
/
70
If i consider a tree whose preorder traversal is given as
[12,30,40,50,50,60,70]
the o/p(preorder traversal) i should get is
[0,1,2,2,1,2,3]
that means the actual node values have to be replaced by their corresponding depths
The visitor function i wrote is as
class DepthVisitor(object):
def __init__(self):
self.result=[]
pass
def fill_depth(self, node):
def count(node, level):
if node!=None:
node.value=level
level+=1
count(node.left, level)
if node.left==None:
count(node.right,level)
count(node, 0)
pass
visitor = DepthVisitor()
pre_order(root, visitor.fill_depth)
the problem is that every time the node is passed to the visitor function it's value gets overwritten to 0 and hence the o/p comes as
[0,0,0,0,0,0,0]
How can i prevent it from overwriting the already visited node values to 0 so as to get the correct o/p.
Or is there any alternate/better way to the same w/o using recursion??
You should initialize your DepthVisitor to have a level attribute by doing self.level = 0. You can then modify your count function to use that persistent level, as it will be stored in the object scope instead of the function scope. You can increment and decrement it as appropriate across function calls.
Related
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 used the search function, and while I found some similar threads I did not find one that exactly covered my issue.
I am attempting to do a look up of a BST using recursion and an in-order traversal , so I want to keep track of the position of the elements.
I have the following code, but it is not doing what I want it to do. It is doing the correct traversal, but the position is not correct.
void startProces(int x)
{
void inOrder(x,*n,*Position)
}
void inOrder(int x, Node *n, int *Position)
{
int counter = *Position;
counter++;
Position = &counter;
}
This is a homework assignment, so please avoid giving me a direct solution. Also please avoid giving me a suggestion that involve having to rewrite the function parameters as I'm locked in. I would appreciate insight on why my position value is not increment properly. I know that my function currently isn't doing anything once it finds the value. I was planning on implementing that once I figured out this issue.
Clarification: I have an insert function, not shown here. If I insert the nodes (15,5,3,12,10,13,6,7,16,20,18,23) I get the in-order traversal (3,5,6,7,10,12,13,15,16,18,20,23). I want this to correspond to (1,2,3,4,5,6,7,8,9,10,11,12). Eventually when I run something like startProcess(10), I want inOrder to print 5.
Your code copies a variable on the stack and passes the address of that variable. So, for each child node, the value will always be the parent node's value plus one, instead of the previously traversed node's value plus one.
Specifically, this line copies it...
int counter = *Position;
The variable Position is a pointer, where counter is a local variable. The pointer points to the address you give it using &. Every time you call inOrder, it creates a new counter variable that's scoped to that function call.
So, this line...
Position = &counter;
sets the pointer to the counter instance in the above function call. All you need to do is pass a pointer to one specific instance instead of the copies.
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.
I am talking with reference to C++.
I know that if an int is declared as static in recursion, its value is not reinitialized in stack-recursion call and the present value is used.
But if a stack becomes empty(or a recursion computation is complete) and then the recursion is called again, will it use the same static value as initialized in first stack call??
I will explain my problem in detail.
I am trying to code level order traversal in spiral form.
1
/ \
2 3
/ \ / \
7 6 5 4
Level order traversal in spiral form will give output 1 2 3 4 5 6 7.
void LevelSpiral(node* root, int level)
{
static int k = level%2;
if(root==NULL)
return;
if(level==1)
{
printf("%d ",root->val);
}
else
{
if(k==0)
{
LevelSpiral(root->left,level-1);
LevelSpiral(root->right,level-1);
}
else
{
LevelSpiral(root->right,level-1);
LevelSpiral(root->left,level-1);
}
}
}
void LevelOrderSpiral(node* root)
{
for(int i=1;i<=maxheight;i++)
LevelSpiral(root,i);
}
LevelOrderSpiral function makes separate LevelSpiral-call for each i. But throughout the code it always uses k=1(which is initialized in the first LevelSpiral-call with i=1) and prints the output as 1 3 2 4 5 6 7.
Shouldn't it print 1 2 3 4 5 6 7 as the function stack is reinitialized for every i?
You need a static variable for it's value to be retained between calls, or from one call to the next recursive call.
Furthermore, recursion wouldn't be the first tool I reach for a breadth-first traversal. I would use a queue of node (safe) pointers (or reference wrappers or whatever). Put the root node in the queue, then loop until the queue is empty removing the front element and enqueueing all of it's child nodes and do what you want with the recently removed element.
Regarding your implementation, you are alternating between going to the left first and going to the right first. level always equals 1 at the row before the one you want to print, so you always traverse your printing row from right to left. You'll see bigger shufflings of the nodes when you have a deeper tree. Draw a sample tree on paper and draw the navigations on it as you follow your code by hand.
I know that if an int is declared as const in recursion, its value is not reinitialized in stack-recursion call and the present value is used.
No, that’s wrong. const has got nothing to do with recursion or reentrancy.
But if a stack becomes empty(or a recursion computation is complete) and then the recursion is called again, will it use the same const value as initialized in first stack call??
A const is a normal (albeit unmodifiable) variable: it is reinitialised whenever the initialisation statement is executed, i.e. on every function call. This is the same for any non-static variable.
static local variables exhibit the behaviour you are describing: they are only executed once, at the first call of that function, and, importantly, they are not reinitialised even after the call stack is “emptied”. It makes no difference whether the function is called repeatedly from outside, or recursively.
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)