Wanted to check if there is a way to construct a binary search tree from only the inorder traversal which will be in sorted order. I am thinking there might be some way we can do it recursively, but not able to figure it out. Any pointers would be appreciated.
A BST has exactly one in-order traversal, but more than one BST can be constructed with a given in-order traversal. Hence, Yes, it is possible to construct a BST with a given in-order traversal, but you may not end up with the same tree whose in-order traversal you've started with.
Check this article for more info: https://www.geeksforgeeks.org/find-all-possible-trees-with-given-inorder-traversal/
Yes it is possible to construct a binary search tree from an inorder traversal.
Observe that an inorder traversal of a binary search tree is always sorted.
There are many possible outcomes, but one can be particularly interested in producing a tree that is as balanced as possible, so to make searches in it efficient. One way to produce an inefficient binary search tree, is to keep adding new nodes to the right of the last inserted node. The resulting binary search tree is then skewed.
If for example the inorder traversal is 1,2,3,4,5,6, we would get this tree:
1
\
2
\
3
\
4
\
5
\
6
That is not very helpful as binary search tree, as it really has degenerated into a single chain, and a search in that tree is no better than performing a search from left to right in the input array.
A much more efficient alternative would be this binary search tree, which has the same inorder traversal:
3
/ \
2 5
/ / \
1 4 6
Algorithm
The algorithm to produce a rather balanced binary search tree can indeed be a recursive one:
If the given array (traversal) is empty return null (emtpy tree)
Take the middle value of the given array (traversal) and create a node for it.
Take the subarray at the left of the selected array value, and perform the algorithm recursively for it. This returns a node (rooting a subtree), which should be attached as left child of the node created in step 2.
Take the subarray at the right of the selected array value, and perform the algorithm recursively for it. This returns a node (rooting a subtree), which should be attached as right child of the node created in step 2.
Return the node created in step 2.
TreeNode* solve(vector<int>& v, int l, int r){
if(l>r){
return NULL;
}
int m = (l+r)/2;
TreeNode* root = new TreeNode(v[m]);
root->left = solve(v, l, m-1);
root-> right = solve(v, m+1,r);
return root;
}
TreeNode *constructFromInOrder(vector<int> &inorder)
{
return solve(inorder, 0, inorder.size()-1);
}
c++ code to convert Inorder to BST
I'm looking at an interview book and the question is:
You have two very large binary trees: T1, with millions of nodes, and
T2, with hundreds of nodes. Create an algorithm to decide if T2 is a
subtree of T1.
The authors mentions this as a possible solution:
Note that the problem here specifies that T1 has millions of
nodes—this means that we should be careful of how much space we use.
Let’s say, for example, T1 has 10 million nodes—this means that the
data alone is about 40 mb. We could create a string representing the
inorder and preorder traversals. If T2’s preorder traversal is a
substring of T1’s preorder traversal, and T2’s inorder traversal is a
substring of T1’s inorder traversal, then T2 is a substring of T1.
I'm not quite sure the logic behind as to why if these are true:
T2-preorder-traversal-string is a substring of T1-preorder-traversal-string
T2-inorder-traversal-string is a substring of T1-inorder-traversal-string
That T2 must be a substring (although I assume the author means subtree) of T1. Can I get an explanation to this logic?
EDIT: User BartoszMarcinkowski brings up a good point. Assume both trees have no duplicate nodes.
I think it is not true. Consider:
T2:
2
/ \
1 3
inorder 123 preorder 213
and
T1:
0
/ \
3 3
/ \
1 1
/ \
0 2
inorder 0123103 preorder 0310213
123 is substring of 0123103, 213 is substring of 0310213, but T2 is not subtree of T1.
Important assumption is that the tree has unique keys.
Now, note that preorder-traversal-string and inorder-traversal-string uniquely identify a binary tree.
Scatch of the proof:
Let T be a tree.
First object in preorder-traversal-string(T) is the root.
Find it in the in the inorder-traversal-string(T) - everything on left of that element is your left subtree L, let's call this substring inorder-traversal-string(L). Everything on right is your right subtree R.
Now, let's focus on the left subtree L.
Clearly all subtrees are separated (they don't mix) in both strings. They are represented as consecutive objects. The only problem is that a priori we don't know where preorder-traversal-string(L) ends in preorder-traversal-string(T).
Note that strings inorder-traversal-string(L) and preorder-traversal-string(L) have the same length. This gives as the place where to cut.
Now you have a subtree described as substrings inorder-traversal-string(L) and preorder-traversal-string(L) so you can repeat the procedure till the end.
Following those steps (inefficient but it is just for the proof) for all subtrees you will uniquely build the tree.
Thus, all subtrees of T1 are described uniquely by corresponding inorder-traversal-string and preorder-traversal-string.
Here is a counter-example to the method.
Consider the tree T1:
B
/ \
A D
/ \
C E
\
F
And the sub-tree T2:
D
/ \
C E
The relevant traversals are:
T1 pre-order: BADCEF
T2 pre-order: DCE
T1 in-order: ABCDEF
T2 in-order: CDE
While DCE is in BADCEF and CDE is in ABCDEF, T2 is not actually a sub-tree of T1. The author's definition of sub-tree must have been different or it was just a mistake.
Related question: Determine if a binary tree is subtree of another binary tree using pre-order and in-order strings
After reading about AVL trees I can't get one question out of my head.
If we have a sorted list of numbers, e.g. [1,2,3,4,5] and we insert them into the AVL tree, wouldn't the tree stay unblanaced because it will go 1-2-3-4-5 (i.e. they will all become right child).
I am asking this because I know that in AVL tree for every internal node v of T, the heights of the children of v can differ by at most 1.
But if we have only 1 child for each node, how can we do this comparison?
An empty tree has height 0, so in your example after adding 1-2-3 the left child of 1 had height 0 and the right had 2, triggering a rotation that makes 2 the root.
I saw this in some paper and someone argued that there can be at most log(n) times rotation when we delete a node of an AVL tree. I believe we can achieve this by generating an AVL tree as lopsided as possible. The problem is how to do this. This will help me a lot about researching the removal rotation thing. Thanks very much!
If you want to make a maximally lopsided AVL tree, you are looking for a Fibonacci tree, which is defined inductively as follows:
A Fibonacci tree of order 0 is empty.
A Fibonacci tree of order 1 is a single node.
A Fibonacci tree of order n + 2 is a node whose left child is a Fibonacci tree of order n and whose right child is a Fibonacci tree of order n + 1.
For example, here's a Fibonacci tree of order 5:
The Fibonacci trees represent the maximum amount of skew that an AVL tree can have, since if the balance factor were any more lopsided the balance factor of each node would exceed the limits placed by AVL trees.
You can use this definition to very easily generate maximally lopsided AVL trees:
function FibonacciTree(int order) {
if order = 0, return the empty tree.
if order = 1, create a single node and return it.
otherwise:
let left = FibonacciTree(order - 2)
let right = FibonacciTree(order - 1)
return a tree whose left child is "left" and whose right child is "right."
Hope this helps!
Consider the situation where you have two lists of nodes of which all you know is that one is a representation of a preorder traversal of some tree and the other a representation of a postorder traversal of the same tree.
I believe it is possible to reconstruct the tree exactly from these two lists, and I think I have an algorithm to do it, but have not proven it. As this will be a part of a masters project I need to be absolutely certain that it is possible and correct (Mathematically proven). However it will not be the focus of the project, so I was wondering if there is a source out there (i.e. paper or book) I could quote for the proof. (Maybe in TAOCP? anybody know the section possibly?)
In short, I need a proven algorithm in a quotable resource that reconstructs a tree from its pre and post order traversals.
Note: The tree in question will probably not be binary, or balanced, or anything that would make it too easy.
Note2: Using only the preorder or the postorder list would be even better, but I do not think it is possible.
Note3: A node can have any amount of children.
Note4: I only care about the order of siblings. Left or right does not matter when there is only one child.
Preorder and postorder do not uniquely define a tree.
In general, a single tree traversal does not uniquely define the
structure of the tree. For example, as we have seen, for both
the following trees, an inorder traversal yields [1,2,3,4,5,6].
4 3
/ \ / \
2 5 2 5
/ \ \ / / \
1 3 6 1 4 6
The same ambiguity is present for preorder and postorder
traversals. The preorder traversal for the first tree above is
[4,2,1,3,5,6]. Here is a different tree with the same preorder
traversal.
4
/ \
2 1
/ \
3 6
\
5
Similarly, we can easily construct another tree whose postorder
traversal [1,3,2,6,5,4] matches that of the first tree above.
You cannot use only one list, because you'll get no sense of the depth of the tree. Thus, you definitely require two or more lists.
Here's my attempt at a solution:
Use your preorder traversal as a means of knowing the ordering of the data. This makes sense because you know the first node is the top, and you know that data further to the left of the traversal belongs to the left of the tree, etc.
Your post order traversal can determine the depth of the tree. For example, let's say I have a structure like this:
1
2 5 6
3 4 7
Where 2 is the parent of 3 and 4, and 5 is the parent of 7.
Preorder: 1 2 3 4 5 7 6
Postorder: 3 4 2 7 5 6 1
We know we start with 1, because it is the first node in the preorder traversal. Then we look at the next number, 2. In the post order, because the number 2 comes BEFORE node 1, we know that 2 has to be a child of 1. Next we look at 3. 3 comes before 2, and thus 3 is a child of 2. 4 is before 2 but after 3, so we know 4 is a child of 2 but NOT a child of 3. Etc.
Now, this may not work if the nodes are not unique, but at the very least its a start to a solution.
Edit: The order of the children is preserved with this solution, simply due to knowing the ordering of the nodes via the preorder traversal, and then knowing the structure via the postorder traversal.
Edit2: The proof may lie here: http://ieeexplore.ieee.org/Xplore/login.jsp?url=http%3A%2F%2Fieeexplore.ieee.org%2Fiel2%2F215%2F626%2F00017225.pdf%3Farnumber%3D17225&authDecision=-203
I think you need to purchase the document, however...
Here is a written proof presented to be a solution:
http://www14.informatik.tu-muenchen.de/lehre/2007WS/fa-cse/tutorials/tutorial09-solutions.pdf
Consider an arbitrary tree T as the quadruple (A, B, C, D), where A is the root node, B is the root node of the first child, C is a vector of any non-empty children of B, and D is a vector of any non-empty siblings of B. The elements of C and D are themselves trees.
Any of A, B, C and D may be empty. If B is empty, so must be C and D; if A, then everything.
Since nodes are unique, the sets of nodes contained anywhere within C and D are disjoint, and neither contains A or B.
Functions pre() and post() generate ordered sequences of the form:
pre(T) = [A, B, pre(C), pre(D)]
post(T) = [post(C), B, post(D), A]
where the function applied to a vector is defined to be the concatenation of the sequences resulting from applying the function to each element in turn.
Now consider the cases:
if A is empty, the output of both functions is the empty sequence []
if B is empty, the output of both functions is just [A]
if C and D are empty, pre(T) = [A, B] and post(T) = [B, A]
if just C is empty, pre(T) = [A, B, D'] and post(T) = [B, D'', A] (where the primes indicate some permutation of the nodes contained within D)
if just D is empty, pre(T) = [A, B, C'] and post(T) = [C'', B, A]
if none are empty, pre(T) = [A, B, C', D'] and post(T) = [C'', B, D'', A]
In all cases we can unambiguously partition the members of the two output sequences into the appropriate subsequences, by using A and B (if present) as delimiters.
The question then is, can we also partition the vector sequences? If we can, then each can be recursively processed and we're done.
Since the result of pre() will always be a chain of sequences starting with A nodes, and the result of post() will always be a chain of sequences ending with A nodes, we can indeed divide them up, provided that the A nodes are never empty.
This is where the process falls down in the case of binary (or indeed any) trees with fixed children that may independently be empty. In our case, however, we have defined C and D to contain only non-empty nodes, and so the reconstruction is guaranteed to work.
Um, I think so, anyway. Obviously this is just an argument, not a formal proof!
Create a binary tree with this restriction that has at least one node that this node has only one child(right or left ,there is no difference).
Now, write its Preorder and Postorder lists. then try to reconstructing the tree from these lists. and you realize that on that node you cannot decide that its child is right or left.
The preorder and postorder traversals are sufficient to reconstruct the tree, assuming the nodes are uniquely named. The key to creating the algorithms to do so is to understand that
X is an ancestor of Y iff X precedes Y in the preorder and is after Y in the postorder.
Given this, we can always find all the descendants of any node. The descendants of X always immediately follow X in the preorder, and precede X in the postorder. So once we know we're interested in producing the subtree rooted at X, we can extract the preorder and postorder traversal for the subtree rooted at X. This leads naturally to a recursive algorithm, once we realize that the node immediately after X must be its leftmost child, if it is a descendant at all.
There is also a stack-based implementation, which iterates through the preorder nodes, and keeps on the stack any nodes which are candidates to be the direct parent of the next preorder node. For each preorder node, repeatedly pop all nodes off the stack which are not parents of the next preorder node. Make that node a child of the top node on the stack, and push the child onto the stack.
As already pointed out by others, a binary tree can not be reconstructed by using only pre and post order traversal. A single child node has ambiguous traversals that cannot identify whether it is left or right child e.g. consider following preorder and postorder traversals:
preorder: a,b
postorder b,a
It can produce both of the following trees
a a
\ /
b b
It is simply not possible to know if b is a's left or right child without any additional information like inorder traversal.
It is not possible to construct a general Binary Tree from preorder and postorder traversals (See this). But if know that the Binary Tree is Full, we can construct the tree without ambiguity. Let us understand this with the help of following example.
Let us consider the two given arrays as pre[] = {1, 2, 4, 8, 9, 5, 3, 6, 7} and post[] = {8, 9, 4, 5, 2, 6, 7, 3, 1};
In pre[], the leftmost element is root of tree. Since the tree is full and array size is more than 1. The value next to 1 in pre[], must be left child of root. So we know 1 is root and 2 is left child. How to find the all nodes in left subtree? We know 2 is root of all nodes in left subtree. All nodes before 2 in post[] must be in left subtree. Now we know 1 is root, elements {8, 9, 4, 5, 2} are in left subtree, and the elements {6, 7, 3} are in right subtree.
1
/ \
/ \
{8, 9, 4, 5, 2} {6, 7, 3}
We recursively follow the above approach and get the following tree.
1
/ \
2 3
/ \ / \
4 5 6 7
/ \
8 9