O(1) Algorithm for Counting Left-Children in Complete Binary Tree - algorithm

I have a complete binary tree (i.e. a tree where "every level, except possibly the last, is completely filled, and all nodes are as far left as possible"). This tree is stored in depth-first, left-to-right order. My problem is, given a node by index and the tree's total size, tell me how many nodes are in that node's left subtree, in O(1).
For example, suppose the tree's total size is 10. This implies the following complete tree (note: the numbers are the node index in the depth-first, left-to-right order):
0
/ \
1 7
/ \ |\
2 5 8 9
/| /
3 4 6
Now, given a node index I need to find how many left-children it has. For this example:
Node 0 has 6 left-children.
Node 1 has 3 left-children.
Node 2 has 1 left-child.
Node 3 has 0 left-children.
Node 4 has 0 left-children.
Node 5 has 1 left-child.
Node 6 has 0 left-children.
Node 7 has 1 left-child.
Node 8 has 0 left-children.
Node 9 has 0 left-children.
Each such query must take O(1) time and be a function only of the node index and tree size (e.g., I cannot store anything in the tree).
I feel like this should be a fairly simple problem, but so-far I haven't been able to figure it out.
Strictly speaking, this is a bit of a simplification of my problem; I actually want 1+ this value, and I'll never call the function on leaves. But the core problem is this.

Related

Reasons and uses to show and print a level on a binary search tree?

I had class yesterday for data structures and my professor was discussing the uses of binary trees, and some info on its levels. I'm starting to work on creating a binary search tree, and I want to include a print function to display level on a tree
Tree example:
3 is root. 3 has two childs, to the left is 2 and and its right is 5.
2 has a child node to its left, 1.
5 has 2 child nodes. 4 is its left child node and 6 is the right child node.
I want to print level 1 of the tree (the 2 and 5)
3
/ \
2 5
/ / \
1 4 6
I want to have a print function in my program to show a level in a tree, but I need some reason for doing that (my professor wants a reason, idk why and i didnt ask). Any reasons to show a level of the tree?

Cache-aware tree impementation

I have a tree where every node may have 0 to N children.
Use-case is the following query: Given pointers to two nodes: Are these nodes within the same branch of the tree?
Examples
q(2,7) => true
q(5,4) => false
By the book (slow)
The straight forward implementation would be to store a pointer to the parent and a pointer to a list of children at each node. But this would lead to bad performance because the tree would be fragmented in memory and therefor not cache-aware.
Question
What would be a good way to represent the tree in compact form? The whole tree has about 100,000 nodes. So it should be possible to find a way to make it fit completely in the CPU-cache.
Binary trees for example are often represented implicitly as an array and are therefor perfect to be completely stored in the CPU-cache (if small enough).
You can pre-allocate a contiguous block of memory where you concatenate the information for all nodes.
Afterwards, each node would only need a way to retrieve the beginning of its information, and the length of that information.
In this case, the information for each node could be represented by the parent, followed by the list of children (let's assume that we use -1 when there is no parent, i.e. for the root).
For example, for the tree posted in the question, the information for node 1 would be: -1 2 3 4, the information for node 2 is: 1 5, and so on.
The contiguous array would be obtained by concatenating these arrays, resulting in something like:
-1 2 3 4 1 5 1 9 10 1 11 12 13 14 2 3 5 5 5 3 3 4 4 4 15 4
Each node would use some metadata to allow retrieving its associated information. As mentioned, this metadata would need to consist of a startIndex and length. E.g. for node 3, we would have startIndex = 6, length = 3, which allows to retrieve the 1 9 10 subarray, indicating that the parent is node 1, and its children are nodes 9 and 10.
In addition, the metadata information can also be stored in the contiguous memory block, at the beginning. The metadata has fixed length for each node (two values), thus we can easily obtain the position of the metadata for a certain node, given its index.
In this way, all the information about the graph will be stored in a contiguous, cache-friendly, memory block.

Number of levels in Binary Tree given the list of datas

Lets consider that, the following is the resultant of the Level Order Traversal of the Binary Tree.
Ex: 1,2,3,4,5,6,7,8
But, I got a question like, with the given list of data, how to compute the total number of levels in the binary tree.
I thought some thing like, Sqrt(8) and doing the Math.Round to it, will yield the result.
But I doubt that, I am wrong.
May I know, what is the perfect to do that.
Thanks in advance...
In the general case, a binary tree with n nodes will have at least 1 + floor(log_2(n)) levels. For example, you can fit 7 nodes on 3 levels, but 8 nodes will take at least 4 levels no matter what.
Also in the general case, the upper limit is n levels in the case of a degenerate binary tree (which looks like a linked list hanging down from the root). Consider your example, where the level-order traversal (also known as breadth-first traversal) is 1 2 3 4 5 6 7 8. The following cases are possible, along with everything in between:
1 1
/ \ \
/ \ 2
2 3 \
/ \ / \ 3
4 5 6 7 \
/ 4
8 \
5
(4 levels) \
6
\
7
\
8
(8 levels)
There are particular types of binary trees for which you can put stronger constraints on the upper limit. For complete or full binary trees, the number of levels is always 1 + floor(log_2(n)), because the shape of the tree depends only on n.
If you label the nodes with an index in breadth-first order, you can compute the level without any traversal in O(1) time. So if you are doing multiple queries, you can do an O(N) BFT and have each query answered in O(1) time.
The formula for the level is:
level = floor(log(index + 1))
Where the log is to the base 2
This link help you How can I calculate the level of a node in a perfect binary tree from its depth-first order index?
The height of a complete binary tree is up to O(logN).
Where N is the number of nodes you fill in the tree.
Note that Big O notation is required due to the fact that the actual height could vary by some addition or scaling factor.
https://www.cs.cmu.edu/~adamchik/15-121/lectures/Trees/trees.html
Level index value either can starts from 0 or 1.
If you are counting the level index starting from 0 (i.e., Root at Level 0) then
#no.of levels = floor(log_2(n))
If you are counting the level index starting from 1 (i.e., Root at Level 1) then
#no.of levels = 1 + floor(log_2(n))

When two trees are equal?

If in-order traversal of two binrary trees (not binary search trees) are the same, does it guarantee that the two trees are the same?
if answer is no, then what about both in-order and pre-order traversal are the same?
Definitely not. The two trees
b
/ \
a d
/ \
c e
and
d
/ \
b e
/ \
a c
both have an inorder traversal of a b c d e. They are, in fact, rotations, an operation which preserves inorder traversal.
NO, and its seen with this simple example
3 2
2 1 3
1 0
0
Both have same inorder traversals [0,1,2,3]
But if inorder and preorder traversals are same then the trees are equal.
I'm thinking "no."
It's possible for two trees to be balanced differently, but have the same "order" of node values. For instance, if, of the set
1,2,3,4,5,6,7
You build a tree:
4
2 6
1 3 5 7
in-order traversal will yield 1,2,3,4,5,6,7.
however, if you choose a different root node (if the list is not sorted correctly beforehand)
5
4 6
2 7
1 3
These two trees will give the same in-order traversal result, but are (clearly) not identical.
or even
7
6
5
4
3
2
1
et cetera.
This is also related to a problem with BSP (binary space partition) trees, typically used in game development collision detection and visibility determination.
The BSP stores triangles in a tree. Each node contains a triangle or facet. The left node contains all children that are "behind" the facet, while the right child contains everything that is in "front." Recurse as expected.
If you pick the left-most facet in the scene as your root, the right child will then own every other facet. If you make a bad decision for the right child, the same thing will happen. It's perfectly possible for one to build a BSP compiler that, through idiotic analysis, builds a "tree" that is actually a list (as in my last example above). The problem is to partition the data set so that each node divides the remaining list as equally as possible. This is one of the reasons that BSPs are typically generated at compile time, as building one for a very complex geometry can take hours to find the/an optimal solution.
Inorder and any one of pre-order or post-order, uniquely define a tree structure. Nothing less.
One thing you can do is use level order
5
4 6
2 7
1 3
lvel order- 5 4 6 2 N N 7 1 3 N N N N N N

Iterative-deepening depth first search using limited memory

This is a follow-up to Find first null in binary tree with limited memory.
Wikipedia says that iterative-deepening depth first search will find the shortest path. I would like an implementation that is limited in memory to k nodes and accesses the tree the least number of times.
For instance, if my binary tree is:
0
1 2
3 4 5 6
7 8 9 10 11 12 13 14
And I'm limited to 5 nodes of memory than my search order is:
mem[0] = read node 0
mem[1] = read node 1
mem[2] = read node 2
mem[3] = read node 3
mem[4] = read node 4 //Now my memory is full. I continue...
mem[3] = read node 5 //overwrite where I stored node 3
mem[4] = read node 6 //overwrite where I stored node 4
Now if my next read is to 7, I need to re-read 3. But if I make my next read to 14, then I don't need to re-read 3 just yet. If the solution is at 14, this will make my algorithm a bit faster!
I'm looking for a general solution; something that will work for any size memory and number of branches per node.
If your nodes link to their parents, and the children of a node will always be enumerated in the same order, you can trace your steps without having to save them.

Resources