Construct Tree from given Inorder and Preorder traversals
Let us consider the below traversals:
Inorder sequence: D B E A F C
Preorder sequence: A B D E C F
In a Preorder sequence, leftmost element is the root of the tree. So we know ‘A’ is root for given sequences. By searching ‘A’ in Inorder sequence, we can find out all elements on left side of ‘A’ are in left subtree and elements on right are in right subtree. So we know below structure now.
A
/ \
/ \
D B E F C
We recursively follow above steps and get the following tree.
A
/ \
/ \
B C
/ \ /
/ \ /
D E F
Algorithm: buildTree()
1) Pick an element from Preorder. Increment a Preorder Index Variable (preIndex in below code) to pick next element in next recursive call.
2) Create a new tree node tNode with the data as picked element.
3) Find the picked element’s index in Inorder. Let the index be inIndex.
4) Call buildTree for elements before inIndex and make the built tree as left subtree of tNode.
5) Call buildTree for elements after inIndex and make the built tree as right subtree of tNode.
6) return tNode.
Thanks to Rohini and Tushar for suggesting the code.
/* program to construct tree using inorder and preorder traversals */
#include<stdio.h>
#include<stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
char data;
struct node* left;
struct node* right;
};
/* Prototypes for utility functions */
int search(char arr[], int strt, int end, char value);
struct node* newNode(char data);
/* Recursive function to construct binary of size len from
Inorder traversal in[] and Preorder traversal pre[]. Initial values
of inStrt and inEnd should be 0 and len -1. The function doesn't
do any error checking for cases where inorder and preorder
do not form a tree */
struct node* buildTree(char in[], char pre[], int inStrt, int inEnd)
{
static int preIndex = 0;
if(inStrt > inEnd)
return NULL;
/* Pick current node from Preorder traversal using preIndex
and increment preIndex */
struct node *tNode = newNode(pre[preIndex++]);
/* If this node has no children then return */
if(inStrt == inEnd)
return tNode;
/* Else find the index of this node in Inorder traversal */
int inIndex = search(in, inStrt, inEnd, tNode->data);
/* Using index in Inorder traversal, construct left and
right subtress */
tNode->left = buildTree(in, pre, inStrt, inIndex-1);
tNode->right = buildTree(in, pre, inIndex+1, inEnd);
return tNode;
}
/* UTILITY FUNCTIONS */
/* Function to find index of value in arr[start...end]
The function assumes that value is present in in[] */
int search(char arr[], int strt, int end, char value)
{
int i;
for(i = strt; i <= end; i++)
{
if(arr[i] == value)
return i;
}
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(char data)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
/* This funtcion is here just to test buildTree() */
void printInorder(struct node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
/* then print the data of node */
printf("%c ", node->data);
/* now recur on right child */
printInorder(node->right);
}
/* Driver program to test above functions */
int main()
{
char in[] = {'D', 'B', 'E', 'A', 'F', 'C'};
char pre[] = {'A', 'B', 'D', 'E', 'C', 'F'};
int len = sizeof(in)/sizeof(in[0]);
struct node *root = buildTree(in, pre, 0, len - 1);
/* Let us test the built tree by printing Insorder traversal */
printf("\n Inorder traversal of the constructed tree is \n");
printInorder(root);
getchar();
}
Time Complexity: O(n^2). Worst case occurs when tree is left skewed. Example Preorder and Inorder traversals for worst case are {A, B, C, D} and {D, C, B, A}.
Please write comments if you find any bug in above codes/algorithms, or find other ways to solve the same problem.
I have also given a tutorial here http://bloggerplugnplay.blogspot.in/2012/11/construction-of-binary-tree-from.html
Well here static is the keyword. If you won't declare preindex as static then the program will fail.
How does the worst case complexity turn out to be O(n^2) for left-skewed trees? I couldn't understand it. Can anyone explain it in detail?
Let the skewed tree be
A / B / D / EThe given inorder traversal would be E D B A, and preorder would be A, B, D, E.
In the above code, we one by one take elements from preorder traversal and search the element in inorder traversal. Searching the first element will take O(n) time, searching the second element will take O(n-1) time, searching the 3rd element will take O(n-2) time, and so on. So total time would be O(n) + O(n-1) + O(n-2) + ... + 1. The sum of this series is O(n*(n-1)/2) which is O(n^2)
/* Paste your code here (You may delete these lines if not writing code) */
We can reduce this search time by using the binary search. right? then it can be done in O(nlogn) time.
Binary Search can only be applied for sorted arrays.
Yes, but then inorder array will always be a sorted array. Right?
Sorry! I was thinking about just the BST.
Hi friends,
Here is my code.
Any suggestions?
#include<stdio.h> struct node { char val; struct node *left; struct node *right; }; struct node *pre_in(char in[],char pre[],int end) { static pre_ind=0;int pos,i; struct node *temp=(struct node *)malloc(sizeof(struct node)); temp->val=pre[pre_ind]; pre_ind++; temp->right=NULL; temp->left=NULL; if(end<0) return NULL; if(end==0)return temp; for(i=0;i<=end;i++) if(in[i]==(temp->val)){break;} temp->left=pre_in(&(in[0]),pre,i-1); temp->right=pre_in(&(in[i+1]),pre,end-i-1); return temp; } print_inorder(struct node *p) { if(p==NULL) return; print_inorder(p->left); printf("\t%c",p->val); print_inorder(p->right); return; } int main() { char in[] = {'D', 'B', 'E', 'A', 'F', 'C'}; char pre[] = {'A', 'B', 'D', 'E', 'C', 'F'}; int length=sizeof(in)/sizeof(in[0]); struct node *p=pre_in(in,pre,length-1); print_inorder(p); return; }Good.
But try without static variables.
But why shouldn't static variables be used?
Please help me.
@tiger: When you call the same function for different inputs, static variables may cause unexpected results. Because static variables may be storing the values of previous function call for a different input.
Ya i get your point. Thank You.
Here is a Java Version of the same problem
http://www.technicalypto.com/2011/12/reconstruct-binary-tree-given-its.html
I got a question saying
"Illustrate the construction of tree of a binary tree given its in order and post order traversal.
Inorder: HDIJEKBALFMCNGO
POSTORDER:HIDJKEBLMFNOGCA
i got two different trees in my answer. Is it right? pls help me out
@Rahul: Looks like you missed something. You can't get two trees for given Inorder and Postorder traversals.
the preIndex seems doesn't change cuz every time it starts from 0?
it would change because it is static.
is there a need to send preOrder end index to buildTree right, If we just increment sequentially, we will be making trees out of leaf nodes as well ?
Given a pre - order and post - order traversal construct a tree.
Assuming that the internal nodes has exactly two children we can uniquely identify the tree.
http://anandtechblog.blogspot.com/2011/06/construct-given-tree-from-pre-order-and.html
Construct a binary tree using the following 10
pre-order and in-order sequences :
Pre-order : 35, 31, 15, 7, 33, 32, 43, 38, 40, 49
In-order : 7, 15, 31, 32, 33, 35, 38, 40, 43, 49
how i make it?
thanks in advance for help.
i think u know that very well,pre order is necessary for making a tree.ok
now
pre order is like that,root left right.
so 35 is our parent node or root.
then covered it by a circle in both pre and in order.
in pre order the next element is 31,now we search the respective position of 31 in in order form.
31 is in the left side of the root node '35' ok
that means 31 is the left child of 35.
similarly we check for all element.
if any other query then contact me on ankitkharkwal@gmail.com
i think u know that very well,pre order is necessary for making a tree.ok
now
pre order is like that,root left right.
so 35 is our parent node or root.
then covered it by a circle in both pre and in order.
in pre order the next element is 31,now we search the respective position of 31 in in order form.
31 is in the left side of the root node '35' ok
that means 31 is the left child of 35.
similarly we check for all element.
if any other query then contact me on ankitkharkwal@gmail.com
Iterative DFS, looking for an efinefcit implementation.I know an explicit stack can be used. One way is, use explicit stack, and keep pushing all the adjacent nodes while exploring each path node in unexplored path. Following this approach, in the worst case, explicit stack will have all the adjacent nodes in the longest path of a node in graph.Where as in recursive approach, the system stack will have max nodes proportional to the depth of the longest node.Any thoughts? I am thinking to keep track of visited node and current exploring node in it's adjacent list. In other words, mitigating system stack functionality by storing stack frame explicitly.
Use Binary Search in
int search(char arr[], int strt, int end, char value)
Since INorder is Increasing sequence, and that would make it O(nlogn) solution
It is a binary tree that we are trying to construct, not a binary search tree. As a result, the inorder traversal of the tree may / may not yield a sorted array.
Additionally, if we wanted to construct a binary search tree, pre-order traversal would have been sufficient.
yup for binary tree i think inorder travesal is ncessary and other travesal can be post/level/pre.
but for BST preoder/postorder alone are sufficient.
but using postoder to construct is very diificult.however preoder traversal alone can be used for constructing binary tree by including some symbol in place of null.
see leetcode
http://www.leetcode.com/2010/09/serializationdeserialization-of-binary.html.
(assume no duplicate chars allowed, otherwise there is some chance that the tree is ambiguous, like the AAA example above)
to optimize, you may pre-process the inorder string, create a hash map between each char and its index. That eliminates the need for a linear search in your search() method, reducing the time complexity of finding the index from linear to constant.
I have done this :-
public BinaryNode BuildTree(int[] inOrder,int[] preOrder,int start,int end,int preIndex) { if (start > end) { return null; } else { BinaryNode newNode = new BinaryNode(preOrder[preIndex]); if (start == end) { return newNode; } int inIndex = SearchInIndex(inOrder,start,end,newNode.data); preIndex++; newNode.left = BuildTree(inOrder,preOrder,start,inIndex-1,preIndex); preIndex++; newNode.right = BuildTree(inOrder,preOrder,inIndex+1,end,preIndex); return newNode; } } public int SearchInIndex(int[] inord, int s, int e, int num) { int i; for(i=s;i<e;i++) { if (inord[i] == num) return i; } return 0; }As an optimization: We can have the first two arguments in[] and pre[] to be passed by reference. To save the process stack
If there are duplicates then i don't think you can construct a tree using preorder and inorder traversal.
Try this
Inorder : AAA
Preorder : AAA
While searching in the inorder list, find the right most un-traversed element.
I didn't get the logic of passing start and end and maintaining static variable.
try this
node* BuildFromInorderPreOrder(int *Inorder, int *Preorder, int length) { if(length == 0) return NULL; if(length == 1) return new node(*Preorder); int RootIndex = 0; for(int i = 0; i < length && Inorder[i]!=*Preorder ; i++, RootIndex++); struct node *CurrentRoot = BuildFromInorderPreOrder(Inorder+RootIndex, Preorder, 1); CurrentRoot->left = BuildFromInorderPreOrder(Inorder, Preorder+1, RootIndex); CurrentRoot->right = BuildFromInorderPreOrder(Inorder + RootIndex + 1, Preorder + RootIndex + 1, length - RootIndex - 1); return CurrentRoot; }and have the class node as
class node { public: int data; struct node* left; struct node* right; node(int i): data(i), left(NULL), right(NULL) {} };in 2nd last line:
Preorder + RootIndex + 1
does not look correct.
is there any need of the argument 'len' in the buildtree function?
I guess it's not being used.
@sandhya: Thanks for pointing this out. We have removed 'len' from the buildtree function. Keep it up!
will the search function work, if there are any duplicates?