Thursday, April 10, 2014

Construct a tree from Inorder and Level order traversals (待写)

原始链接


Given inorder and level-order traversals of a Binary Tree, construct the Binary Tree. Following is an example to illustrate the problem.
BinaryTree
Input: Two arrays that represent Inorder
       and level order traversals of a 
       Binary Tree
in[]    = {4, 8, 10, 12, 14, 20, 22};
level[] = {20, 8, 22, 4, 12, 10, 14};

Output: Construct the tree represented 
        by the two arrays.
        For the above two arrays, the 
        constructed tree is shown in 
        the diagram on right side
 思想就是每次在level order中,提取first node 作为当前的root。
然后,在in order中找到所有在其前面的值(作为左子树)。同时在level order的数组中抽取所有左子树的value。
same for the right subtree.
repeat above .
 
 
 
We strongly recommend to minimize the browser and try this yourself first.
The following post can be considered as a prerequisite for this.
Construct Tree from given Inorder and Preorder traversals
Let us consider the above example.
in[] = {4, 8, 10, 12, 14, 20, 22};
level[] = {20, 8, 22, 4, 12, 10, 14};
In a Levelorder sequence, the first element is the root of the tree. So we know ’20′ is root for given sequences. By searching ’20′ in Inorder sequence, we can find out all elements on left side of ‘20’ are in left subtree and elements on right are in right subtree. So we know below structure now.
             20
           /    \
          /      \ 
 {4,8,10,12,14}  {22}   
Let us call {4,8,10,12,14} as left subarray in Inorder traversal and {22} as right subarray in Inorder traversal.
In level order traversal, keys of left and right subtrees are not consecutive. So we extract all nodes from level order traversal which are in left subarray of Inorder traversal. To construct the left subtree of root, we recur for the extracted elements from level order traversal and left subarray of inorder traversal. In the above example, we recur for following two arrays.
// Recur for following arrays to construct the left subtree
In[]    = {4, 8, 10, 12, 14}
level[] = {8, 4, 12, 10, 14} 
Similarly, we recur for following two arrays and construct the right subtree.
// Recur for following arrays to construct the right subtree
In[]    = {22}
level[] = {22} 
Following is C++ implementation of the above approach.
/* program to construct tree using inorder and levelorder traversals */
#include <iostream>
using namespace std;
/* A binary tree node */
struct Node
{
    int key;
    struct Node* left, *right;
};
/* Function to find index of value in arr[start...end] */
int search(int arr[], int strt, int end, int value)
{
    for (int i = strt; i <= end; i++)
        if (arr[i] == value)
            return i;
    return -1;
}
// n is size of level[], m is size of in[] and m < n. This
// function extracts keys from level[] which are present in
// in[].  The order of extracted keys must be maintained
int *extrackKeys(int in[], int level[], int m, int n)
{
    int *newlevel = new int[m], j = 0;
    for (int i = 0; i < n; i++)
        if (search(in, 0, m-1, level[i]) != -1)
            newlevel[j] = level[i], j++;
    return newlevel;
}
/* function that allocates a new node with the given key  */
Node* newNode(int key)
{
    Node *node = new Node;
    node->key = key;
    node->left = node->right = NULL;
    return (node);
}
/* Recursive function to construct binary tree of size n from
   Inorder traversal in[] and Level Order traversal level[].
   inSrt and inEnd are start and end indexes of array in[]
   Initial values of inStrt and inEnd should be 0 and n -1.
   The function doesn't do any error checking for cases
   where inorder and levelorder do not form a tree */
Node* buildTree(int in[], int level[], int inStrt, int inEnd, int n)
{
    // If start index is more than the end index
    if (inStrt > inEnd)
        return NULL;
    /* The first node in level order traversal is root */
    Node *root = newNode(level[0]);
    /* If this node has no children then return */
    if (inStrt == inEnd)
        return root;
    /* Else find the index of this node in Inorder traversal */
    int inIndex = search(in, inStrt, inEnd, root->key);
    // Extract left subtree keys from level order traversal
    int *llevel  = extrackKeys(in, level, inIndex, n);
    // Extract right subtree keys from level order traversal
    int *rlevel  = extrackKeys(in + inIndex + 1, level, n-inIndex-1, n);
    /* construct left and right subtress */
    root->left = buildTree(in, llevel, inStrt, inIndex-1, n);
    root->right = buildTree(in, rlevel, inIndex+1, inEnd, n);
    // Free memory to avoid memory leak
    delete [] llevel;
    delete [] rlevel;
    return root;
}
/* Uti;ity function to print inorder traversal of binary tree */
void printInorder(Node* node)
{
    if (node == NULL)
       return;
    printInorder(node->left);
    cout << node->key << " ";
    printInorder(node->right);
}
/* Driver program to test above functions */
int main()
{
    int in[]    = {4, 8, 10, 12, 14, 20, 22};
    int level[] = {20, 8, 22, 4, 12, 10, 14};
    int n = sizeof(in)/sizeof(in[0]);
    Node *root = buildTree(in, level, 0, n - 1, n);
    /* Let us test the built tree by printing Insorder traversal */
    cout << "Inorder traversal of the constructed tree is \n";
    printInorder(root);
    return 0;
}
Output:
Inorder traversal of the constructed tree is
4 8 10 12 14 20 22
An upper bound on time complexity of above method is O(n3). In the main recursive function, extractNodes() is called which takes O(n2) time.
The code can be optimized in many ways and there may be better solutions. Looking for improvements and other optimized approaches to solve this problem.

No comments:

Post a Comment