Check if a binary tree is subtree of another binary tree

本文介绍了一种在O(n)时间内判断一棵树是否为另一棵树子树的算法,通过存储并比较两棵树的中序和前序遍历结果来实现。包括详细步骤、代码实现和复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given two binary trees, check if the first tree is subtree of the second one. A subtree of a tree T is a tree S consisting of a node in T and all of its descendants in T.

The subtree corresponding to the root node is the entire tree; the subtree corresponding to any other node is called a proper subtree.

For example, in the following case, Tree1 is a subtree of Tree2.

        Tree1
          x 
        /    \
      a       b
       \
        c


        Tree2
              z
            /   \
          x      e
        /    \     \
      a       b      k
       \
        c

We have discussed a O(n2) solution for this problem. In this post a O(n) solution is discussed. The idea is based on the fact that inorder and preorder/postorder uniquely identify a binary tree. Tree S is a subtree of T if both inorder and preorder traversals of S arew substrings of inorder and preorder traversals of T respectively.

Following are detailed steps.

1) Find inorder and preorder traversals of T, store them in two auxiliary arrays inT[] and preT[].

2) Find inorder and preorder traversals of S, store them in two auxiliary arrays inS[] and preS[].

3) If inS[] is a subarray of inT[] and preS[] is a subarray preT[], then S is a subtree of T. Else not.

We can also use postorder traversal in place of preorder in the above algorithm.

Let us consider the above example

Inorder and Preorder traversals of the big tree are.
inT[]   =  {a, c, x, b, z, e, k}
preT[]  =  {z, x, a, c, b, e, k}

Inorder and Preorder traversals of small tree are
inS[]  = {a, c, x, b}
preS[] = {x, a, c, b}

We can easily figure out that inS[] is a subarray of
inT[] and preS[] is a subarray of preT[]. 

EDIT

The above algorithm doesn't work for cases where a tree is present
in another tree, but not as a subtree. Consider the following example.

        Tree1
          x 
        /    \
      a       b
     /        
    c         


        Tree2
          x 
        /    \
      a       b
     /         \
    c            d

Inorder and Preorder traversals of the big tree or Tree2 are.

Inorder and Preorder traversals of small tree or Tree1 are

The Tree2 is not a subtree of Tree1, but inS[] and preS[] are
subarrays of inT[] and preT[] respectively.

The above algorithm can be extended to handle such cases by adding a special character whenever we encounter NULL in inorder and preorder traversals. Thanks to Shivam Goel for suggesting this extension.

Following is C++ implementation of above algorithm.

#include <iostream>
#include <cstring>
using namespace std;
#define MAX 100
 
// Structure of a tree node
struct Node
{
     char key;
     struct Node *left, *right;
};
 
// A utility function to create a new BST node
Node *newNode( char item)
{
     Node *temp =  new Node;
     temp->key = item;
     temp->left = temp->right = NULL;
     return temp;
}
 
// A utility function to store inorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
void storeInorder(Node *root, char arr[], int &i)
{
     if (root == NULL)
     {
         arr[i++] = '$' ;
         return ;
     }
     storeInorder(root->left, arr, i);
     arr[i++] = root->key;
     storeInorder(root->right, arr, i);
}
 
// A utility function to store preorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
void storePreOrder(Node *root, char arr[], int &i)
{
     if (root == NULL)
     {
         arr[i++] = '$' ;
         return ;
     }
     arr[i++] = root->key;
     storePreOrder(root->left, arr, i);
     storePreOrder(root->right, arr, i);
}
 
/* This function returns true if S is a subtree of T, otherwise false */
bool isSubtree(Node *T, Node *S)
{
     /* base cases */
     if (S == NULL)  return true ;
     if (T == NULL)  return false ;
 
     // Store Inorder traversals of T and S in inT[0..m-1]
     // and inS[0..n-1] respectively
     int m = 0, n = 0;
     char inT[MAX], inS[MAX];
     storeInorder(T, inT, m);
     storeInorder(S, inS, n);
     inT[m] = '\0' , inS[n] = '\0' ;
 
     // If inS[] is not a substring of preS[], return false
     if ( strstr (inT, inS) == NULL)
         return false ;
 
     // Store Preorder traversals of T and S in inT[0..m-1]
     // and inS[0..n-1] respectively
     m = 0, n = 0;
     char preT[MAX], preS[MAX];
     storePreOrder(T, preT, m);
     storePreOrder(S, preS, n);
     preT[m] = '\0' , preS[n] = '\0' ;
 
     // If inS[] is not a substring of preS[], return false
     // Else return true
     return ( strstr (preT, preS) != NULL);
}
 
// Driver program to test above function
int main()
{
     Node *T = newNode( 'a' );
     T->left = newNode( 'b' );
     T->right = newNode( 'd' );
     T->left->left = newNode( 'c' );
     T->right->right = newNode( 'e' );
 
     Node *S = newNode( 'a' );
     S->left = newNode( 'b' );
     S->left->left = newNode( 'c' );
     S->right = newNode( 'd' );
 
     if (isSubtree(T, S))
         cout << "Yes: S is a subtree of T" ;
     else
         cout << "No: S is NOT a subtree of T" ;
 
     return 0;
}

Output:

No: S is NOT a subtree of T

Time Complexity: Inorder and Preorder traversals of Binary Tree take O(n) time. The functionstrstr() can also be implemented in O(n) time using KMP string matching algorithm.

Auxiliary Space: O(n)

Thanks to Ashwini Singh for suggesting this method. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值