【二叉树】C++判断一棵树是否为另一棵树的子树【需考虑海量数据处理中的栈溢出】

问题

假设有两棵非常大的二叉树:T1,有几百万个结点;T2, 有几百个结点。设计一个算法,判断T2是否为T1的子树。
子树:如果T1有这么一个节点n,从n开始的子树与T2的值一模一样,则T2为T1的子树。

思路

1. 如何判断

遍历T1,每遍历到一个结点current,则采用广度优先遍历方式从current开始,同时遍历T1子树和T2并做比较。若子树current与树T2完全相同,则返回true;若不相同,则返回false,继续遍历T1到下一个结点。

2. 如何遍历

用C++解决该问题需考虑海量数据处理中的栈溢出问题。系统栈大小一般为4M或8M。如果采用递归方法遍历,那么容易造成函数调用栈被冲爆。比如,当T1含有800万个结点,且所有节点都最多含有左子树,则递归遍历所需函数调用栈大小约为8M,容易被冲爆。

因此,对T1采用迭代遍历方法,通过分配堆内存来防止栈溢出;T2所含结点较少,在不考虑极端情况的条件下,我们采用递归遍历方法,代码会更简洁。

测试:

功能测试:进行了简单的功能测试。
边界值测试:未进行边界值测试。
特殊输入测试:进行了简单的特殊输入测试。

核心代码:

/********************************************
 *  Author        : Dong Huaan
 *  Email         : [email protected]
 *  Filename      : SubTree.cpp
 *  Creation time : 2018-01-04 14:28:31
 *  Last modified : 2018-01-04 15:38:59
 *  Description   : ---
 *******************************************/

// TOC: worst about: O(N + kM)
// SOC: worst about: O(log(N))

#include
#include
#include"BinaryTree.h"

// tree root1 is too big, should not use recursive method
// to traverse it,for it may lead to stack overflow.
// tree root1: iteravisely pre order traverse;
// tree root2: recursively BST;

bool isEqual(BTNode *root1, BTNode *root2)
{
    if(!root1 && !root2) return true;
    if(!root1 || !root2) return false;
    if(root1->data != root2->data) return false;

    return isEqual(root1->left, root2->left)
           && isEqual(root1->right, root2->right);
}

bool isSubTree(BTNode *root1, BTNode *root2)
{
    if(!root1 && root2) return false;
    if(!root2) return true;

    std::stack *stack = new std::stack;
    BTNode *temp = root1;
    stack->push(temp);
    bool result = false;

    while(!stack->empty())
    {
        temp = stack->top();
        result = isEqual(temp, root2);
        if(result) return true;

        stack->pop();

        if(temp->right) stack->push(temp->right);
        if(temp->left) stack->push(temp->left);
    }

    delete stack;

    return false;
}

测试代码:

void test()
{
    BTNode *root1 = nullptr;
    BTNode *root2 = nullptr;

    createBinaryTree(root1);
    createBinaryTree(root2);

    std::cout << "pre order traverse tree root1: ";
    preOrdertraverseBinaryTree_Recur(root1);

    std::cout << "\npre order traverse tree root2: ";
    preOrdertraverseBinaryTree_Recur(root2);

    bool result = isSubTree(root1, root2);
    std::cout << "\nresult: " << result << std::endl;
}

int main()
{
    test();
}

测试结果

【二叉树】C++判断一棵树是否为另一棵树的子树【需考虑海量数据处理中的栈溢出】_第1张图片

你可能感兴趣的:(数据结构与算法)