我检查了互联网上的所有内容,以了解如何检查树是否是另一个树的子集。通过子集,我的意思是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) );
}
在使用给定的示例运行我的代码之后,我的输出返回第一个树不是第二个树的子集,当它实际上是一个子集时。
答案 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)
)其中n
是tree1
和m
的节点数tree2
答案 1 :(得分:1)
二进制搜索树支持对元素进行有效的排序迭代。以非递减顺序维护每个树的元素上的迭代器。重复以下步骤,直到确定结果:
TRUE
。FALSE
。FALSE
。基本实现是最差情况O(n + m)
,其中n
和m
是两棵树的相应大小。如果较大的树是平衡的,那么通过提到的优化,您还可以通过O(n log m)
将其绑定,如果第二个树比第一个树大得多,这将非常有用。 (无论树是否平衡,O(n + m)
绑定仍然适用。)