📌  相关文章
📜  检查给定的前序、中序和后序遍历是否属于同一棵树

📅  最后修改于: 2022-05-13 01:57:18.185000             🧑  作者: Mango

检查给定的前序、中序和后序遍历是否属于同一棵树

给定某棵树的前序、中序和后序遍历。编写一个程序来检查它们是否都属于同一棵树。
例子:

Input : Inorder -> 4 2 5 1 3
        Preorder -> 1 2 4 5 3
        Postorder -> 4 5 2 3 1
Output : Yes
Explanation : All of the above three traversals are of 
the same tree              1
                         /   \
                        2     3
                      /   \
                     4     5

Input : Inorder -> 4 2 5 1 3
        Preorder -> 1 5 4 2 3
        Postorder -> 4 1 2 3 5
Output : No 

解决这个问题的最基本方法是首先使用三个给定遍历中的两个构造一棵树,然后对这个构造的树进行第三次遍历,并将其与给定的遍历进行比较。如果两个遍历相同,则打印 Yes,否则打印 No。这里,我们使用 Inorder 和 Preorder 遍历来构造树。我们也可以使用 Inorder 和 Postorder 遍历而不是 Preorder 遍历来构建树。您可以参考这篇文章,了解如何从给定的 Inorder 和 Preorder 遍历构造一棵树。构造树后,我们将获得这棵树的后序遍历,并将其与给定的后序遍历进行比较。
下面是上述方法的实现:

C++
/* C++ program to check if all three given
   traversals are of the same tree */
#include 
using namespace std;
 
// A Binary Tree Node
struct Node
{
    int data;
    struct Node *left, *right;
};
 
// Utility function to create a new tree node
Node* newNode(int data)
{
    Node *temp = new Node;
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}
 
/* Function to find index of value in arr[start...end]
   The function assumes that value is present in in[] */
int search(int arr[], int strt, int end, int value)
{
    for (int i = strt; i <= end; i++)
    {
        if(arr[i] == value)
            return i;
    }
}
 
/* Recursive function to construct binary tree
   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 */
Node* buildTree(int in[], int 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 */
    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;
}
 
/* function to compare Postorder traversal
   on constructed tree and given Postorder */
int checkPostorder(Node* node, int postOrder[], int index)
{
    if (node == NULL)
        return index;
  
    /* first recur on left child */
    index = checkPostorder(node->left,postOrder,index);
      
    /* now recur on right child */
    index = checkPostorder(node->right,postOrder,index);   
   
    /* Compare if data at current index in
       both Postorder traversals are same */
    if (node->data == postOrder[index])
        index++;
    else
        return -1;
 
    return index;
}
 
// Driver program to test above functions
int main()
{
    int inOrder[] = {4, 2, 5, 1, 3};
    int preOrder[] = {1, 2, 4, 5, 3};
    int postOrder[] = {4, 5, 2, 3, 1};
 
    int len = sizeof(inOrder)/sizeof(inOrder[0]);
 
    // build tree from given
    // Inorder and Preorder traversals
    Node *root = buildTree(inOrder, preOrder, 0, len - 1);
 
    // compare postorder traversal on constructed
    // tree with given Postorder traversal
    int index = checkPostorder(root,postOrder,0);
 
    // If both postorder traversals are same
    if (index == len)
        cout << "Yes";
    else
        cout << "No";
 
    return 0;
}


Java
/* Java program to check if all three given
traversals are of the same tree */
import java.util.*;
class GfG {
    static int preIndex = 0;
 
// A Binary Tree Node
static class Node
{
    int data;
    Node left, right;
}
 
// Utility function to create a new tree node
static Node newNode(int data)
{
    Node temp = new Node();
    temp.data = data;
    temp.left = null;
    temp.right = null;
    return temp;
}
 
/* Function to find index of value in arr[start...end]
The function assumes that value is present in in[] */
static 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;
}
 
/* Recursive function to construct binary tree
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 */
static Node buildTree(int in[], int pre[], int inStrt, int inEnd)
{
 
    if(inStrt > inEnd)
        return null;
 
    /* Pick current node from Preorder traversal
    using preIndex and increment preIndex */
    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;
}
 
/* function to compare Postorder traversal
on constructed tree and given Postorder */
static int checkPostorder(Node node, int postOrder[], int index)
{
    if (node == null)
        return index;
 
    /* first recur on left child */
    index = checkPostorder(node.left,postOrder,index);
     
    /* now recur on right child */
    index = checkPostorder(node.right,postOrder,index);    
     
    /* Compare if data at current index in
    both Postorder traversals are same */
    if (node.data == postOrder[index])
        index++;
    else
        return -1;
 
    return index;
}
 
// Driver program to test above functions
public static void main(String[] args)
{
    int inOrder[] = {4, 2, 5, 1, 3};
    int preOrder[] = {1, 2, 4, 5, 3};
    int postOrder[] = {4, 5, 2, 3, 1};
 
    int len = inOrder.length;
 
    // build tree from given
    // Inorder and Preorder traversals
    Node root = buildTree(inOrder, preOrder, 0, len - 1);
 
    // compare postorder traversal on constructed
    // tree with given Postorder traversal
    int index = checkPostorder(root,postOrder,0);
 
    // If both postorder traversals are same
    if (index == len)
        System.out.println("Yes");
    else
        System.out.println("No");
 
}
}


Python3
# Python3 program to check if
# all three given traversals
# are of the same tree
class node:
   
    def __init__(self, x):
       
        self.data = x
        self.left = None
        self.right = None
 
preIndex = 0
 
# Function to find index of value
# in arr[start...end]. The function
# assumes that value is present in in
def search(arr, strt, end, value):
   
    for i in range(strt, end + 1):
        if(arr[i] == value):
            return i
 
# Recursive function to construct
# binary tree of size lenn from
# Inorder traversal in and Preorder
# traversal pre[].  Initial values
# of inStrt and inEnd should be 0
# and lenn -1. The function doesn't
# do any error checking for cases
# where inorder and preorder do not
# form a tree
def buildTree(inn, pre, inStrt, inEnd):
   
    global preIndex
 
    if(inStrt > inEnd):
        return None
 
    # Pick current node from Preorder
    # traversal using preIndex and
    # increment preIndex
    tNode = node(pre[preIndex])
    preIndex += 1
 
    # If this node has no children
    # then return
    if (inStrt == inEnd):
        return tNode
 
    # Else find the index of this
    # node in Inorder traversal
    inIndex = search(inn, inStrt,
                     inEnd, tNode.data)
 
    # Using index in Inorder traversal,
    # construct left and right subtress
    tNode.left = buildTree(inn, pre, inStrt,
                           inIndex - 1)
    tNode.right = buildTree(inn, pre,
                            inIndex + 1, inEnd)
 
    return tNode
 
# function to compare Postorder traversal
# on constructed tree and given Postorder
def checkPostorder(node, postOrder, index):
    if (node == None):
        return index
 
    # first recur on left child
    index = checkPostorder(node.left,
                           postOrder,
                           index)
 
    # now recur on right child
    index = checkPostorder(node.right,
                           postOrder,
                           index)
 
    # Compare if data at current index in
    # both Postorder traversals are same
    if (node.data == postOrder[index]):
        index += 1
    else:
        return - 1
 
    return index
 
# Driver code
if __name__ == '__main__':
   
    inOrder = [4, 2, 5, 1, 3]
    preOrder = [1, 2, 4, 5, 3]
    postOrder = [4, 5, 2, 3, 1]
    lenn = len(inOrder)
 
    # build tree from given
    # Inorder and Preorder traversals
    root = buildTree(inOrder, preOrder,
                     0, lenn - 1)
 
    # compare postorder traversal on
    # constructed tree with given
    # Postorder traversal
    index = checkPostorder(root, postOrder, 0)
 
    # If both postorder traversals are same
    if (index == lenn):
        print("Yes")
    else:
        print("No")
 
# This code is contributed by Mohit Kumar 29


C#
/* C# program to check if all three given
traversals are of the same tree */
using System;
     
public class GfG
{
    static int preIndex = 0;
 
    // A Binary Tree Node
    class Node
    {
        public int data;
        public Node left, right;
    }
 
    // Utility function to create a new tree node
    static Node newNode(int data)
    {
        Node temp = new Node();
        temp.data = data;
        temp.left = null;
        temp.right = null;
        return temp;
    }
 
    /* Function to find index of
    value in arr[start...end]
    The function assumes that
    value is present in in[] */
    static 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;
    }
 
    /* Recursive function to construct
    binary tree 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 */
    static Node buildTree(int []In, int []pre,
                            int inStrt, int inEnd)
    {
 
        if(inStrt > inEnd)
            return null;
 
        /* Pick current node from Preorder traversal
        using preIndex and increment preIndex */
        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;
    }
 
    /* function to compare Postorder traversal
    on constructed tree and given Postorder */
    static int checkPostorder(Node node, int []postOrder, int index)
    {
        if (node == null)
            return index;
 
        /* first recur on left child */
        index = checkPostorder(node.left,postOrder,index);
 
        /* now recur on right child */
        index = checkPostorder(node.right,postOrder,index);    
 
        /* Compare if data at current index in
        both Postorder traversals are same */
        if (node.data == postOrder[index])
            index++;
        else
            return -1;
 
        return index;
    }
 
    // Driver code
    public static void Main()
    {
        int []inOrder = {4, 2, 5, 1, 3};
        int []preOrder = {1, 2, 4, 5, 3};
        int []postOrder = {4, 5, 2, 3, 1};
 
        int len = inOrder.Length;
 
        // build tree from given
        // Inorder and Preorder traversals
        Node root = buildTree(inOrder, preOrder, 0, len - 1);
 
        // compare postorder traversal on constructed
        // tree with given Postorder traversal
        int index = checkPostorder(root, postOrder, 0);
 
        // If both postorder traversals are same
        if (index == len)
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
 
    }
}
 
/* This code is contributed PrinciRaj1992 */


Javascript


C++
#include 
using namespace std;
struct Node {
    int data;
    Node *left, *right;
 
    Node(int val)
    {
        data = val;
        left = right = NULL;
    }
};
Node* buildTreeFromInorderPreorder(
    int inStart, int inEnd, int& preIndex, int preorder[],
    unordered_map& inorderIndexMap,
    bool& notPossible)
{
    if (inStart > inEnd)
        return NULL;
 
    // build the current Node
    int rootData = preorder[preIndex];
    Node* root = new Node(rootData);
    preIndex++;
 
    // find the node in inorderIndexMap
    if (inorderIndexMap.find(rootData)
        == inorderIndexMap.end()) {
        notPossible = true;
        return root;
    }
 
    int inorderIndex = inorderIndexMap[rootData];
    if (!(inStart <= inorderIndex
          && inorderIndex <= inEnd)) {
        notPossible = true;
        return root;
    }
 
    int leftInorderStart = inStart,
        leftInorderEnd = inorderIndex - 1,
        rightInorderStart = inorderIndex + 1,
        rightInorderEnd = inEnd;
 
    root->left = buildTreeFromInorderPreorder(
        leftInorderStart, leftInorderEnd, preIndex,
        preorder, inorderIndexMap, notPossible);
 
    if (notPossible)
        return root;
 
    root->right = buildTreeFromInorderPreorder(
        rightInorderStart, rightInorderEnd, preIndex,
        preorder, inorderIndexMap, notPossible);
 
    return root;
}
 
bool checkPostorderCorrect(Node* root, int& postIndex,
                           int postorder[])
{
    if (!root)
        return true;
 
    if (!checkPostorderCorrect(root->left, postIndex,
                               postorder))
        return false;
    if (!checkPostorderCorrect(root->right, postIndex,
                               postorder))
        return false;
 
    return (root->data == postorder[postIndex++]);
}
 
void printPostorder(Node* root)
{
    if (!root)
        return;
 
    printPostorder(root->left);
    printPostorder(root->right);
 
    cout << root->data << ", ";
}
 
void printInorder(Node* root)
{
    if (!root)
        return;
 
    printInorder(root->left);
    cout << root->data << ", ";
    printInorder(root->right);
}
 
bool checktree(int preorder[], int inorder[],
               int postorder[], int N)
{
    // Your code goes here
    if (N == 0)
        return true;
 
    unordered_map inorderIndexMap;
    for (int i = 0; i < N; i++)
        inorderIndexMap[inorder[i]] = i;
 
    int preIndex = 0;
 
    // return checkInorderPreorder(0, N - 1, preIndex,
    // preorder, inorderIndexMap) &&
    // checkInorderPostorder(0, N - 1, postIndex, postorder,
    // inorderIndexMap);
 
    bool notPossible = false;
 
    Node* root = buildTreeFromInorderPreorder(
        0, N - 1, preIndex, preorder, inorderIndexMap,
        notPossible);
 
    if (notPossible)
        return false;
 
    int postIndex = 0;
 
    return checkPostorderCorrect(root, postIndex,
                                 postorder);
}
 
// Driver program to test above functions
int main()
{
    int inOrder[] = { 4, 2, 5, 1, 3 };
    int preOrder[] = { 1, 2, 4, 5, 3 };
    int postOrder[] = { 4, 5, 2, 3, 1 };
 
    int len = sizeof(inOrder) / sizeof(inOrder[0]);
 
    // If both postorder traversals are same
    if (checktree(preOrder, inOrder, postOrder, len))
        cout << "Yes";
    else
        cout << "No";
 
    return 0;
}


输出
Yes

使用哈希映射存储中序元素索引的高效算法:

在从中序和前序遍历构建树时,我们需要检查中序和前序遍历对于某些树本身是否有效,如果是,则继续构建树,但如果不能从给定的中序和前序构建有效的二叉树遍历,那么我们必须停止构建树并返回 false。我们还可以在 O(n) 时间内从中序和前序遍历构建树,使用 hashmap 存储中序元素数组的索引。

C++

#include 
using namespace std;
struct Node {
    int data;
    Node *left, *right;
 
    Node(int val)
    {
        data = val;
        left = right = NULL;
    }
};
Node* buildTreeFromInorderPreorder(
    int inStart, int inEnd, int& preIndex, int preorder[],
    unordered_map& inorderIndexMap,
    bool& notPossible)
{
    if (inStart > inEnd)
        return NULL;
 
    // build the current Node
    int rootData = preorder[preIndex];
    Node* root = new Node(rootData);
    preIndex++;
 
    // find the node in inorderIndexMap
    if (inorderIndexMap.find(rootData)
        == inorderIndexMap.end()) {
        notPossible = true;
        return root;
    }
 
    int inorderIndex = inorderIndexMap[rootData];
    if (!(inStart <= inorderIndex
          && inorderIndex <= inEnd)) {
        notPossible = true;
        return root;
    }
 
    int leftInorderStart = inStart,
        leftInorderEnd = inorderIndex - 1,
        rightInorderStart = inorderIndex + 1,
        rightInorderEnd = inEnd;
 
    root->left = buildTreeFromInorderPreorder(
        leftInorderStart, leftInorderEnd, preIndex,
        preorder, inorderIndexMap, notPossible);
 
    if (notPossible)
        return root;
 
    root->right = buildTreeFromInorderPreorder(
        rightInorderStart, rightInorderEnd, preIndex,
        preorder, inorderIndexMap, notPossible);
 
    return root;
}
 
bool checkPostorderCorrect(Node* root, int& postIndex,
                           int postorder[])
{
    if (!root)
        return true;
 
    if (!checkPostorderCorrect(root->left, postIndex,
                               postorder))
        return false;
    if (!checkPostorderCorrect(root->right, postIndex,
                               postorder))
        return false;
 
    return (root->data == postorder[postIndex++]);
}
 
void printPostorder(Node* root)
{
    if (!root)
        return;
 
    printPostorder(root->left);
    printPostorder(root->right);
 
    cout << root->data << ", ";
}
 
void printInorder(Node* root)
{
    if (!root)
        return;
 
    printInorder(root->left);
    cout << root->data << ", ";
    printInorder(root->right);
}
 
bool checktree(int preorder[], int inorder[],
               int postorder[], int N)
{
    // Your code goes here
    if (N == 0)
        return true;
 
    unordered_map inorderIndexMap;
    for (int i = 0; i < N; i++)
        inorderIndexMap[inorder[i]] = i;
 
    int preIndex = 0;
 
    // return checkInorderPreorder(0, N - 1, preIndex,
    // preorder, inorderIndexMap) &&
    // checkInorderPostorder(0, N - 1, postIndex, postorder,
    // inorderIndexMap);
 
    bool notPossible = false;
 
    Node* root = buildTreeFromInorderPreorder(
        0, N - 1, preIndex, preorder, inorderIndexMap,
        notPossible);
 
    if (notPossible)
        return false;
 
    int postIndex = 0;
 
    return checkPostorderCorrect(root, postIndex,
                                 postorder);
}
 
// Driver program to test above functions
int main()
{
    int inOrder[] = { 4, 2, 5, 1, 3 };
    int preOrder[] = { 1, 2, 4, 5, 3 };
    int postOrder[] = { 4, 5, 2, 3, 1 };
 
    int len = sizeof(inOrder) / sizeof(inOrder[0]);
 
    // If both postorder traversals are same
    if (checktree(preOrder, inOrder, postOrder, len))
        cout << "Yes";
    else
        cout << "No";
 
    return 0;
}
输出
Yes

时间复杂度: O(N)
辅助空间: O(N),其中 N 是树中的节点数。