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)
Related
Is there a way I can create a for loop such that, given any starting location the loop will subsequently iterate through the right-most element of each level? Given some heap:
If you were inside a make_heap function, you may start at (n-2)/2) which would be the node denoted by the red twelve.
Now, given some start location (n-2)/2, is it possible to iterate such that the subsequent values of the loop will be 6 -> 2 -> 0 (array location of the right most elements above the initial level, which is the red number minus one) which correspond to 14 -> 24 -> 25.
My initial implementation looks like
using std::size_t;
size_t n = last - first; // size of heap
for(size_t start = (n-2)/2;
start > 0;
start = (size_t)pow(2, (size_t)log2(start)-1))
{
std::cout << start << std::endl;
}
My thinking was that start is equal to 2log2(start)-1, which means the previous level.
However this only yields 11, 4, 2, 1 (add one for the corresponding node location in red). It in theory should be 11, 6, 2, 0. Any ideas?
Assuming your indices are 1-based, it is straight forward to compute the parent and the child nodes of a node given its index n:
you get the parent node using n / 2
you get the left child node using n * 2
you get the rigth child node using n * 2 + 1
Since arrays in C++ are 0-base you may need to strategically add/substract 1 to convert between node and array indices.
To get to the right children of the the parent nodes you'd keep the index p of the current parent node, replacing it using p = p / 2 in each direction and access the node at p * 2 + 1. Of course, if make_heap() is anything like std::make_heap() it doesn't need to do anything like that. It merely needs to "bubble up" the new node while its parent is bigger the node.
I'm having the following problem:
There are a lot of nodes and several of them are already connected, but not all. We have to add connections such that each node is connected with any other(not neccessary directly). We do not want to change any of the existing connections.
The nodes have to be connected with the least amount of lines (the current connections already follow this rule). Also a path from one node to another must pass through the least amount of other nodes. We want to know the maximum number of nodes on any path, when everything is connected in an optimal way.
Input:
The following data is given by user input:
• You get two integers: the number 1 ≤ p ≤ 1.000.000 of nodes and the
number 0 ≤ l ≤ p − 1 of existing connections.
• Then l lines with each two integers a and b between 0 and p − 1 (inclusive), denoting the endpoints of a connection.
Output:
The output should be an integer that represents the maximum number of nodes on any path.(so without the beginning and endpoints)
So for example when we have as input p = 6, l = 4 and the connections 2-0, 1-0, 5-3 and 4-3 the output should be 2.
I already wrote a program in c++ that does the following:
int main(){
int p, l;
cin >> p >> l;
for (int i = 0; i < l; i++){
int a, b;
cin >> a >> b;
// store the connection a,b somehow
}
// solve the problem
cout << answer << endl;
}
I thought of storing the connections in an p - 1 times p - 1 array, with a 1 if the line exists and 0 otherwise. Furtermore I need something to decide how to make connections in an optimal way and compute the maximum amount of nodes on each path. I'm only allowed to use the standard library of C++.
Could someone please help me with this? Thanks in advance!
This sounds like a basic algorithms homework...
Given your existing graph, find the maximum path. Unless you have only two nodes, this will be your answer.
Connect all your new nodes to any node that is not a leaf node of your maximum path.
(Lines that connect nodes are called "edges".)
Let me know if I have misunderstood your problem.
edit
Here is a simple graph.
The maximal path is (a,b,c) [which is the same as (c,b,a) -- we'll always order the two leaves so that the smallest comes first].
(a)--(b)--(c)
I can find it by picking any leaf node -- a node with exactly 1 edge -- and finding my way to another leaf node.
The furthest leaf node will be the longest/maximal path from that node.
Do it again from the leaf node you just found, and you will have the longest/maximal path for the entire graph.
Let's examine how that works with a new graph:
(a)--(b)--(c)--(d)--(e)--(f)
|
(s)
I'm going to start at node (s). If I find the longest path from it I will find node (f). Node (f) must be one of the endpoints on the longest path in the graph. (I'll leave it to you to think about why.)
Now, I start again at node (f). The longest path from (f) leads to (a). I now have the longest path in the graph: (a,b,c,d,e,f).
Here is another graph:
(a)--(b)--(c)
|
(d)
There are a number of longest paths to choose from. (a,b,c), (a,b,d), and (c,b,d). What matters is that they all exist and have the same length.
Now, to which node should I connect a new node (e) so that I don't change the longest path? Easy:
(e)
|
(a)--(b)--(c)
|
(d)
You can guarantee this by only attaching a new node to nodes that are not leaf nodes.
As for your question about how to represent the graph, your idea will work fine, but remember, you have p nodes, not p-1. So, for example, I can represent my 3-node graph as:
from
a b c
a 0 1 0
to b 1 0 1
c 0 1 0
Notice the columns: a only leads to one other node. Likewise, c only leads to one other node.
However, b's column shows that b leads to two other nodes (which is more than one).
Hence, a and c are leaves; b is not.
If I add a new node, I will want to connect it only to nodes that have more than one node already:
a b c d a b c d
a 0 1 0 0 a 0 1 0 0
b 1 0 1 0 --> b 1 0 1 1
c 0 1 0 0 c 0 1 0 0
d 0 0 0 0 d 0 1 0 0
Hope this helps.
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.
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
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.