查找第一个树是否是第二个树的子集

时间:2016-04-18 01:11:44

标签: c tree binary-tree subtree

我检查了互联网上的所有内容,以了解如何检查树是否是另一个树的子集。通过子集,我的意思是issubset函数应该return 1如果第一个树的所有元素都出现在第二个树中 否则0。请注意,根据元素的插入顺序,具有相同元素集的两个树可以具有非常不同的形状。给出以下示例作为树:

Elements of the first tree
             4
           /  \
         2     6
        / \   / \
       1   2  5  7 


Elements of the second Tree
            6
          /   \
         4     7
        /  \
       2    5
      / \
     1   2    

以下代码遍历树,然后检查值:

int issubset(nodeT **tree1, nodeT **tree2) {

    if( *tree2 == NULL)
        return TRUE;
    if(*tree1 == NULL)
        return FALSE;

    if(are_identical(&(*tree1),&(*tree2)))
        return TRUE;

    return issubset(&(*tree1)->pLeft, &(*tree2)) || issubset(&(*tree2)->pRight, &(*tree2));
}

int are_identical(nodeT **tree1, nodeT **tree2) {
    nodeT **temp;
    int iFound = 0, i, r;   
    if( *tree2 == NULL)
        return TRUE;

    if( (*tree1) ==NULL && (*tree2) ==NULL) {
        return FALSE;
    }

    if( (*tree1)->iValue != (*tree2)->iValue) {
        if(iFound = 0)
            return TRUE;

        i = issubset(&(*tree1)->pLeft, &(*tree2));
        if( i ==0) {
            r = issubset(&(*tree1)->pRight, &(*tree2));
            return r;
        }

        return i;
    }   

    return((*tree1)->iValue == (*tree2)->iValue && are_identical(&(*tree1)->pLeft, &(*tree2)->pLeft) && 
           are_identical(&(*tree1)->pRight, &(*tree2)->pRight) );
}

在使用给定的示例运行我的代码之后,我的输出返回第一个树不是第二个树的子集,当它实际上是一个子集时。

2 个答案:

答案 0 :(得分:3)

我不确定我理解你的问题,但我仍然试着给你答案。从您的示例中我假设您正在使用二叉搜索树。但我不知道你正在使用什么样的二叉树,我会假设一个通用的方案。我想如果树有点平衡,那么也许你可以得到更好的算法。

由于你有二进制搜索树,你可以假设一个函数search(root, key),它返回一个有效指针,指向包含key的节点(如果找到这个)或者NULL

另外,我假设你知道每棵树的节点数。因此,如果0的节点数少于tree1,则可以返回tree。否则方法如下:

int tree1_contained_in_tree2(node * tree1, node * tree2)
{
  if (tree1 == NULL) // am I visiting a empty tree?
    return 1;

  // so I am sure tree1 is not NULL ==> I search the contained key in tree2
  if (search(tree2, tree1->key) == NULL)
    return 0; // tree1->key does not belong to tree2

  // here tree1->key belongs to tree1 so, I test with the subtrees of root
  return tree1_contained_in_tree2(tree1->left, tree2) && 
         tree1_contained_in_tree2(tree1->right, tree2);    
}

我更喜欢使用指向节点的简单指针而不是双指针。我认为你可以调整我的方法。

如果O(n log m)达到平衡,则算法为tree2(否则为O(n m))其中ntree1m的节点数tree2

的节点数

答案 1 :(得分:1)

二进制搜索树支持对元素进行有效的排序迭代。以非递减顺序维护每个树的元素上的迭代器。重复以下步骤,直到确定结果:

  • 如果第一个迭代器没有更多元素,则返回TRUE
  • 如果第二个迭代器没有更多元素,请返回FALSE
  • 如果第一个迭代器的当前元素小于第二个迭代器的当前元素,则返回FALSE
  • 如果第一个迭代器的当前元素等于第二个迭代器的当前元素,则更新两个迭代器。
  • 如果第一个树的当前元素大于第二个树的当前元素,则更新第二个迭代器。 (您可以通过跳过某些元素来优化它。)

基本实现是最差情况O(n + m),其中nm是两棵树的相应大小。如果较大的树是平衡的,那么通过提到的优化,您还可以通过O(n log m)将其绑定,如果第二个树比第一个树大得多,这将非常有用。 (无论树是否平衡,O(n + m)绑定仍然适用。)