Binary tree to general tree - data-structures

I know that from a general tree you can construct a unique binary tree, but is the reverse true? i.e can you get a unique general tree from a binary tree?

Yes. The following transformation is reversible:
Given a general tree with ordered but not indexed children,
encode the first child as the left child of its parent, and each other node as a right child of its (former) sibling.
The reverse is:
Given a binary tree with distinguished left and right children, read the left child of a node as its first child and the right child as its next sibling.
So, the following tree
a
/|\
b c d
is encoded as
a
/
b
\
c
\
d
while the following tree
a
/ \
b c
|
d
is encoded as
a
/
b
/ \
d c
(read: d is the first child of b, c is the sibling of a).
Note that you can encode any rooted forest (with ordered components, otherwise the representation is not unique) by assigning a sibling to the root, so this
a
/ \
b c
\ \
d e
would be read as
a c e
/ \
b d
here is another method to get a unique general (undirected) tree from a binary tree:
a vertex binary tree may have 0...3 graph neighbors.
append 12 nodes to the root
append 8 nodes to each left child
append 4 nodes to each right child
this operation is reversible:
label the node with at least 12 neighbors "root". If not unique, fail.
label each node with 8..11 neighbors "left".
label each node with 4..7 neighbors "right".
remove all leaves
orient all edges away from the root
if any node has more than one left child or more than one right child, fail.
So,
There is a bijection between ordered rooted trees and binary trees (first and second algorithm).
Since any general tree can be arbitrarily rooted, there is a injection from general (directed or undirected) trees to binary trees.
There is an injection from binary trees to general undirected trees (third algorithm)
Since there is an injection from binary trees to general trees and back, there must exist a bijection between general (directed or undirected) trees and binary trees.

I feel unlikely. Usually, binary tree distinguishes left child and right child. However, general trees don't.
How are we supposed to get a unique general tree from these two binary tree.
X X
/ \ / \
Y Z Z Y
And how about these two?
X X
/ \
Y Y
On the other hand,
If you choose to not distinguish left or right child of a binary tree, or choose to respect the sequence children appears in a general tree, just map each binary tree to itself. That will be a unique general tree for each binary tree.

Related

Number of possible balanced binary trees?

Given number of nodes N (ie a preorder seq of length N) in a balanced binary tree,I am trying to find the number b of possible balanced binary trees that can be formed.
I noticed it is possible that there might be variations in the leaves as well as the higher-level nodes:
A
/ \
B C
/ / \
D E F
/
G
The constraint is generally applied recursively to every subtree. That is, the tree is only balanced if:
1.The left and right subtrees' heights differ by at most one, AND
2.The left subtree is balanced, AND
3.The right subtree is balanced

Prove that this assumption doesn't work for all binary search trees

(Binary search tree is a binary tree where each node can have 2 children atmost, the right being larger than the node, and the left should be smaller than the node.)
I have a theory that i want to disprove. It says that for any binary tree, the if we take a search path (call it S) to a leaf node, then any node on the LEFT of S must be smaller than any node on S, and any node of the RIGHT must be larger than any node on S. In other words: node on left < node on S < node on right. Is there any counter-example to disprove this theory?
For example if we have this tree:
A search path for node K would be M->F->H->K
The set of nodes on the left contains C, A, D, G
The set on the right contains V,S,P,T,X,W
What is a good counter example?
Thank you.
This isn't really an answer, but it wouldn't fit in a comment...
I think your definition of "binary search tree" is a bit lacking - after all, this would meet your definition:
B
\
C
/ \
A D
However, that's not a true binary search tree - your definition lacks the recursive relationship. In a binary search tree, all elements in the left subtree of a node are less than the node label, and all elements in the right subtree are greater - not just the immediate children.
Perhaps having a more precise definition would help you in thinking about your "theory".

Check if a binary tree has two identical subtrees

I want to write a method to find whether a tree has at least a pair of identical subtrees, the subtrees have to be identical in both value and structure.
Suppose you are given a tree as follows:
a
/ \
b f
/ / \
c g d
/ / /
d h e
/
e
This would return true because we have a pair of identical trees with root d.
My thought is to traverse each node and build a map of node name mapped to list of tree nodes. In each iteration, we check if current node name is in the map or not. If it's in, then we can call boolean isSameTree(TreeNode t1, TreeNode t2) function with current node against every node in the list of tree nodes to see if they are identical.
The time complexity would be O(n^3). And I wonder if we can do better than that!
Your example tree also has a pair of identical trees with root e. In general, if two trees are identical then either they are both leaves or they have subtrees which are identical. So you can simplify your test to checking whether all of the leaves in the original tree are distinct, which takes O(n) hashing operations and average case Theta(n) equality comparisons unless the hash is very poor.

Reconstruct a tree from a list, with depth info encapsulated in the entry of list

We built a list from a tree (not necessarily a binary search tree) via depth first traversal.
Each entry inside is a pair (k, d), k is the key of a node and d is the depth of that node.
Now we need to construct the original tree back from the list.
How do we do it?
Note
tree is not necessarily a binary search tree
we do not know whether the depth first traversal is pre-order, in-order or post-order.
My question is
Can we achieve this reverse engineering under the conditions? I know for binary search tree, we need at least two traversal lists (e.g., inorder and postorder list) to reconstruct the original tree.
How? if possible
Things to note:
The in-order traversal produces a unique tree
The pre-order and post-order don't:
You can't differentiate between these two:
1 1
/ \
2 2
I'll just generate the one on the left (doing this makes it a lot easier).
What we can say right away:
If the first node is the root (i.e. not depth 0):
We're either doing in-order with an empty left subtree, or pre-order.
If the last node is the root:
We're either doing in-order with an empty right subtree, or post-order.
If neither of the above:
We're doing in-order traversal.
For the two cases above where we don't know which traversal to do, the simplest approach is to try to generate the trees for both possible traversals, and discard whichever one doesn't work (based on the below restrictions), if either.
Some restrictions:
For in-order, we can't go right or up if the current node is empty.
For pre-order, we can't go left or right if the current node is empty.
For post-order, we have to go up after setting the current node - we can't go left or right without having set the current node.
In all cases, we try to go left before going right before going up.
By 'go left' or 'go right', I mean creating an (empty) left or right child and traversing to that node.
By 'go up', I mean simply traversing upwards in the already created tree.
Based on the above restrictions, it should be easy to write an algorithm to generate the tree. As an example for in-order:
If the new node's depth is deeper than the current node's depth:
If the current node is empty and doesn't have a left child, we can just create a left child and set that as the current node
Otherwise, if the current node is not empty and doesn't have a right child, we can just create a right child and set that as the current node
Otherwise, if the depth is the same as the current node and the current node is empty,
set that node's value to the new node
If none of the above cases triggered and the current node is empty,
set the parent of the current node as the current node
If none of the above cases triggered, fail
If 1.1, 1.2, or 3 triggered, repeat from 1.
Example:
Input: (f, 2), (g, 2), (b, 1), (i, 2), (c, 1), (a, 0)
Since (a, 0) is the root, we're doing either in-order or post-order.
So then we generate 2 subtrees:
in-order post-order
. .
/ /
. .
/ /
f f
(. indicates an empty node)
When we get (g, 2), we can already discard the in-order tree, as we can't go right or up from f's parent, because it is empty, so we're stuck.
Then we continue with post-order:
.
/
.
/ \
f g
.
/
b
/ \
f g
.
/ \
b .
/ \ /
f g i
.
/ \
b c
/ \ /
f g i
a
/ \
b c
/ \ /
f g i
I'm not sure what you mean by pre/post/in-order, a single DFS run with the depth data should allow you to reconstruct the tree if you know the time of first visiting each node (I guess that would amount to a "pre-order" by your definition). In-order isn't even defined well in non-binary trees (would the parent appear after the first node? after the second? what if there's a single child?)
If you can tell the order of discovering each node, you can just go over the list while the depth increases, creating more and more children (and keeping track of the last node encountered at each depth), and once you get a non increasing depth you know for sure how many levels up you need to go in order to place the next node.
Two list-consecutive nodes with the same depth would be siblings of the same parent, and in general, if the last node had depth d1 and you now encounter d2, then you need to go up d1-d2+1 levels back up the current branch before attaching the next node.
A depth of d is enough to identify the parent (it would have to be the last node of depth d-1), since in DFS you can't encounter any other parent of that depth without first completely exploring the entire branch descending from from the previous one.
A slightly better proof - let v be a node along your list of depth d. It would have to descend of some node of depth d-1.
Let's assume the list is
[(v0,d0), ... (v, d), ...]
The parent can't be in the remainder of the list since this means you reached a child before its parent - impossible while traversing a tree. So the parent has to be in the first ... section. Let's assume it's not the last d-1-depth node prior to v - so let's say the list is -
[(v0,d0), ... (vi, d-1), ... (vj, d-1), ...(v, d), ...]
if v is the child of vi, than when traversing the original tree your DFS reached vi, missed v somehow, then passed to another branch originating from some ancestor of vi, found vj there, and only then came back to vi and encountered v. This violates the DFS premise.
Maybe I'm missing something, but:
If the first pair in the sequence has depth zero, it's a pre-order traversal.
If the last pair in the sequence has depth zero, it's a post-order traversal.
Else it's an in-order traversal.

Is this a full binary tree?

Here's the binary tree in question. The leaves are a, b, c, d and the edges are labelled 0 or 1.
.
/ \
a .
/ \
b .
/ \
c d
It seems to me that it is a full binary tree, as every node is either a leaf or has two child nodes, however I have this feeling that we were told it is not a full binary tree. If not, why is it not?
If a node has a child that is a leaf, does that not count as a child node?
You are confusing a perfect binary tree with a full binary tree. A perfect binary tree is a full binary tree with all leaf nodes at the same level. So yes, the picture is a full binary tree.
A leaf is defined as a node without a child node.
Thus, a full binary tree is a binary tree in which each node has either zero or two children.
Wikipedia helps very well with definitions. Make sure you check it out.
Yes, a tree with each node has zero or two children, it is binary tree.

Resources