Compute index for leafs in a tree structure - c++

Given a tree (binary) structure, with depth N. Is it possible to compute some lookup index for mapping leaf nodes.
Each node knows its parent, and its childs(left and right) if its not a leaf.
My Idea was something like saying rootnode is index 0, then left:1,left:left:2, left:left:left:3, left:left:right:4, left:right:left:5,left:right:right:6,right:7,right:left:8 e.g.
So given a leaf node, how can i compute the index smartest.
Other solutions are accepted also, if its smarter to give the leafs indexes from 0,1...L, where L is the number of leafs.

If you wish to represent a tree in an array, the simplest is to take the layers of tree one at a time.
0
/ \
/ \
1 2 [0, 1, 2, 3, 4, 5, 6]
/ \ / \
3 4 5 6
This way, finding the parent is simply: (index-1)/2. And finding the two children is just 2*index and 2*index + 1.

In my Tree structure (Quadtree and Octree) I am using a binary representation of the indexes of each node. e.g. 32 bit (for max 32 level) for each dimension.
So I can compute the complete index (or path) of a leaf by the formula
path.x = (unsigned int)(leaf.position.x * pow(2,32));
leaf.position.x musst be in a range from 0...1
The only constraint (I think) for this method is that the data you are storing musst be in a specific range, so that you can devide it by your area size.
If this is possible for your usecase read more at
Simple and Efficient Traversal Methods for
Quadtrees and Octrees

Related

Pre-Order Traversals Of All Possible Binary Trees Given In-Order Traversal

I was looking at questions on binary trees, and I came across the following:
Given the in-order traversal of a binary tree, print the pre-order traversals of all possible binary trees satisfying the given in-order traversal.
For e.g, if the in-order traversal is: {4, 5, 7}
The possible trees are:
4 4 5 7 7
\ \ / \ / /
5 7 4 7 4 5
\ / \ /
7 5 5 4
Therefore, the pre-order traversals are:
4 5 7
4 7 5
5 4 7
7 4 5
7 5 4
The solution I came up with:
Traverse the given in-order list. Upon each iteration, select an element from the list and make it the root of our tree. All elements preceding the current one will be part of the left subtree and all elements succeeding it will form the right subtree. We can then recursively do the same for the left and right subtrees.
For instance, in the above example, I begin by selecting 4 as the root of my tree. Now since there are no elements preceding 4, I cannot have a left subtree. I look at the remaining elements. They will form the right subtree. I select 5 to be the root of this subtree. For this, I am only left with one choice: to construct the right subtree of 5 from 7. That gives the first tree of the example.
Now, I keep 4 as the root, and instead of selecting 5, I select 7 as the root of the right subtree of 4. This leads me to the second tree of the example above.
That much is fine. The problem comes up with the code. I've spent quite sometime on translating the above solution to code. But I haven't been completely successful.
This is what I've tried in C++:
void solve(vector<int> inOrder, int beg, int end, string &s, bool &flag)
{
for(int i = beg; i <= end; ++i)
{
s += to_string(inOrder[i]);
flag = false;
solve(inOrder, beg, i - 1, s, flag);
solve(inOrder, i + 1, end, s, flag);
if(s.size() == inOrder.size()) {flag = true; cout << s << endl;}
if(s.size() && flag) {s.pop_back();}
}
}
I use a string to store the current permutation of elements in the pre-order traversal. Elements are appended to the string when a permutation satisfies the in-order traversal.
Naturally, elements must be subsequently removed from the string to make way for other permutations. However, I haven't been able to figure out when to remove an element. In the above code, I append an element the first time it is encountered, and I start removing elements when the string has size equal to that of the in-order list.
So, let's say I begin with 4. I append 4 to the string. I do the same for 5 and then 7. Now the string size equals the total number of elements. So I remove the last one. My string is now 45. Since there are no more possible combinations with the current string, I remove 5. I'm left with 4. Now, I can append 7 and then 5, leading to 475. This works fine in this case, but I haven't been able to make it work for other combinations. It fails when I begin by making 5 as the root, instead of 4.
So my question is, how exactly should I proceed to solve the above problem? Am I even doing it the right way? Or should I give up this approach and think of something else? If yes, what direction should I proceed in?
I'm not looking for an exact solution, only a hint as to what I'm missing or what I could do better.

Predict the required number of preallocated nodes in a kD-Tree

I'm implementing a dynamic kD-Tree in array representation (storing the nodes in std::vector) in breadth-first fashion. Each i-th non-leaf node have a left child at (i<<1)+1 and a right child at (i<<1)+2. It would support incremental insertion of points and collection of points.
However I'm facing problem determining the required number of possible nodes to incrementally preallocate space.
I've found a formula on the web, which seems to be wrong:
N = min(m − 1, 2n − ½m − 1),
where m is the smallest power of 2 greater than or equal to n, the
number of points.
My implementation of the formula is the following:
size_t required(size_t n)
{
size_t m = nextPowerOf2(n);
return min(m - 1, (n<<1) - (m>>1) - 1);
}
function nextPowerOf2 returns a power of 2 largest or equal to n
Any help would be appreciated.
Each node of a kd-tree divides the space into two spaces. Hence, the number of nodes in the kd-tree depends on how you perform this division:
1) If you divide them in the midpoint of the space (that is, if the space is from x1 to x2, you divide the space with the x3=(x1+x2)/2 line), then:
i) Each point will be allocated its own node, and
ii) Each intermediate node will be empty.
In this case, the number of nodes will depend on how large the coordinates of the points are. If the coordinates are bounded by |X|, then the total number of nodes in the kd-tree should be slightly less than log |X| * n (more precisely, around log |X| * n - n log n + 2n) in the worst case. To see this, consider the following way to add the points: you add multiple collections, each collection has two extremely nearby points located at random. For each pair of point, the tree will need to continuously divide the space log |X| times, and if log |X| is significantly larger than log n, creating log |X| intermediate nodes in the process.
2) If you divide them by using a point as a dividing line, then each node (including the intermediate nodes) will contain a point. Thus, the total number of nodes is simply n. However, note that using a point to divide the space may yield to a very bad performance if the points are not given in a random order (for example, if the points are given in an ascending order of X, the depth of the tree would be O(n). For comparison, the depth of the tree in (1) is at most O(log |X|) ).

Finding PostOrder traversal from LevelOrder traversal without constructing the tree

Given a binary tree where value of each internal node is 1 and leaf node is 0. Every internal
node has exactly two children. Now given level order traversal of this tree return postorder
traversal of the same tree.
This question can be easily solved if I construct a tree and then do its postorder traversal. Although it is O(n) time. But is it possible to print postOrder traversal without building up the tree.
It's definitely possible.
Considering it's a Full Binary Tree, once the number of nodes is determined, theoretically, the shape of tree is unique.
Deem the level order traversal as an array, for example, 1 2 3 4 5 6 7.
It represents such tree:
1
2 3
4 5 6 7
What you want to get is the post order traversal: 4 5 2 6 7 3 1.
The first step is calculate how deep the tree was:
depth = ceil(log(2, LevelOrderArray.length)) // =3 for this example
after that, set up a counter = 0, and extract nodes from the bottom level of the original array, one by one:
for(i=0, i<LevelOrderArray.length, i++){
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth-1) +i ] //4,5,....
counter++; //1,2,.....
}
But notice that once the counter can be divided by 2, that means you need to retrieve another node from upper level:
if(counter mod 2^1 == 0)
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth -2) + (++i) ] // =2 here,
//which is the node you need after 4 and 5, and get 3 after 6 and 7 at the 2nd round
Don't ++ the counter here, because the counter represents how many nodes you retrieved from the bottom level.
Every time 2^2 = 4 nodes was pop out, retrieve another node from 3rd level (counting from bottom)
if(counter mod 2^2 == 0)
postOrderArray[i] = LevelOrderArray[ 2 ^ (depth -3) + (++i) ] // =1
Every time 2^3 = 8 nodes was pop out, again, retrieve another node from 4th level
.... until the loop is finished.
It's not strict C++ code, only the concept. If you fully understand the algorithm, the value of tree nodes doesn't matter at all, even though there are all 0 and 1. The point is although you didn't build up the tree in program, but build it up in your mind instead, and convert it into algorithm.

Finding the location of a parent node in a binary tree

So I need help coming up with an expression that will always give me the location of a child's parent node in a binary tree. Here is an example of a problem my teacher will put on our exam:
"Consider a complete binary tree with exactly 10,000 nodes, implemented with an array starting at index 0 . The array is populated in order by extracting elements from the tree one level at a time from left to right. Suppose that a node has its value stored in location 4999. Where is the value stored for this node’s parent?"
My teacher did not tell us how to solve a problem like this. She just said "Draw a binary tree and find a pattern." I did just that but i could not come up with anything! please help. thanks.
The following is entirely using integer division. I.e. fractional remainders are dropped. For any given node index N, the children of that node will always be in locations 2N+1 and 2(N+1) in the same array.
Therefore, The parent of any node N > 0 in such an array will always be at index (N-1)/2.
Parent to Child Examples:
Parent 0: children 1,2
Parent 1: children 3,4
Parent 2: children 5,6
Parent 3: children 7,8
etc...
Child to Parent Examples:
Child 8 : Parent = (8-1)/2 = 7/2 = 3
Child 7 : Parent = (7-1)/2 = 6/2 = 3
Child 6 : Parent = (6-1)/2 = 5/2 = 2
Child 5 : Parent = (5-1)/2 = 4/2 = 2
So for your problem:
(4999-1)/2 = 4998/2 = 2499
Note: remember this, since you'll be using it extensively when you start coding array-based heap-sort algorithms.
Thanks for all your help guys. And I found the answer to my question!
The general algorithm for finding the location of the parent node is:
[i + (root - 1)] / 2 where i is the location of the given node and root is the location of the root. So in the given problem above the root starts at position 0. so the equation to find the parent node of any node is [i + (0 - 1)] / 2 = (i - 1) / 2
Now let's say the root started at position 3, then the equation would be [i + (3 - 1)] / 2
= (i + 2) / 2!!!! This is the algorithm I needed. Most of you helped me solve the one problem i provided but i actually needed the general solution for a binary tree whose root can start at any postions; not just at zero
It seems this is how the array elements map back to tree based on array indices
0
1 2
3 4 5 6
If so, then the parent of index n is at floor( (n - 1) / 2 ) (for n != 0)
If you do the log2 of the number requested (4999) and take the integer part it will give you the closest power of two to the number (12). It is 2^12 = 4096.
The parent of the nodes between 4096 and 2^13 - 1, are the ones between 2^11 and 2^12 - 1. And for each pair of nodes in the first range you have its parent in the second. So you can map them taking the integer part of the half of the difference (4999 - 4096) and adding it to the parent range start (2048).
So you will have floor of 903 / 2, and add it to 2048, getting 2499.
Note that I didn't make a precise calculation, take the strategy of the answer not the results.
You can put this algorithm in a mathematical expression, with a little work.
Hope it helps!
The parent node is at n/2 if n is even.
It is at (n-1)/2 if n is odd.
So you can remember it as math.ceil((n-1)/2)

Confused about definition of a 'median' when constructing a kd-Tree

Im trying to build a kd-tree for searching through a set of points, but am getting confused about the use of 'median' in the wikipedia article. For ease of use, the wikipedia article states the pseudo-code of kd-tree construction as:
function kdtree (list of points pointList, int depth)
{
if pointList is empty
return nil;
else
{
// Select axis based on depth so that axis cycles through all valid values
var int axis := depth mod k;
// Sort point list and choose median as pivot element
select median by axis from pointList;
// Create node and construct subtrees
var tree_node node;
node.location := median;
node.leftChild := kdtree(points in pointList before median, depth+1);
node.rightChild := kdtree(points in pointList after median, depth+1);
return node;
}
}
I'm getting confused about the "select median..." line, simply because I'm not quite sure what is the 'right' way to apply a median here.
As far as I know, the median of an odd-sized (sorted) list of numbers is the middle element (aka, for a list of 5 things, element number 3, or index 2 in a standard zero-based array), and the median of an even-sized array is the sum of the two 'middle' elements divided by two (aka, for a list of 6 things, the median is the sum of elements 3 and 4 - or 2 and 3, if zero-indexed - divided by 2.).
However, surely that definition does not work here as we are working with a distinct set of points? How then does one choose the correct median for an even-sized list of numbers, especially for a length 2 list?
I appreciate any and all help, thanks!
-Stephen
It appears to me that you understand the meaning of median, but you are confused with something else. What do you mean be distinct set of points?
The code presented by Wikipedia is a recursive function. You have a set of points, so you create a root node and choose a median of the set. Then you call the function recursively - for the left subtree you pass in a parameter with all the points smaller than the split-value (the median) of the original list, for the right subtree you pass in the equal and larger ones. Then for each subtree a node is created where the same thing happens. It goes like this:
First step (root node):
Original set: 1 2 3 4 5 6 7 8 9 10
Split value (median): 5.5
Second step - left subtree:
Set: 1 2 3 4 5
Split value (median): 3
Second step - right subtree:
Set: 6 7 8 9 10
Split value (median): 8
Third step - left subtree of left subtree:
Set: 1 2
Split value (median): 1.5
Third step - right subtree of left subtree:
Set: 3 4 5
Split value (median): 4
Etc.
So the median is chosen for each node in the tree based on the set of numbers (points, data) which go into that subtree. Hope this helps.
You have to choose an axis with as many element on one side than the other. If the number of points is odd or the points are positioned in such a way that it isn't possible, just choose an axis to give an as even repartition as possible.