证明一个二叉树是另一个的子树

时间:2015-09-23 01:06:23

标签: algorithm tree tree-traversal

假设您有两个二叉树,并且您想知道一个是否是另一个树的子树。一种解决方案是获取两个树的inorder和preorder遍历,并检查候选子树的遍历是否是另一个树的相应遍历的子串。我读了几篇关于这个解决方案的帖子。一个discussion表明inorder和preorder遍历都是必要的。有人可以解释为什么它们足够吗?为什么如果tree2的inorder和preorder遍历是tree1的子串,那么tree2是tree1的子树?

2 个答案:

答案 0 :(得分:1)

人们一致认为二叉树可以用左/右关系表示它的节点上的顺序。这意味着左侧部分位于右侧部分之前。如果订单相同,您可以调用树。因此,按顺序字符串表示顺序,如果要检查等效性,则仅按顺序检查(按定义)就足够了。 但是当你想要检查树的完全相等时,我们必须找到我们如何区分等价树的方式。例如,它可以是水平顺序检查。但是对于子树级别顺序不适合,因为子树的级别顺序字符串是分开的。对于预订,您可以在树的其他部分之前遍历子树形式根。

假设等价树不相等,那么在预订中遍历一切都将是相等的,直到第一次不同为止。可能会发生两种情况。

1)一棵树的节点值与另一棵树的值不同。这意味着预订字符串不同,因为您按预先的顺序遍历树。

2)儿童签名(没有孩子,只有左,右,两个孩子)不同。但在这种情况下,易于理解的是,有序会发生变化,而树木则不相同,这与条件相矛盾。

请注意,这仅适用于所有节点都是唯一的。如果你的所有节点都是“a”,那么无论你走路如何,你的字符串总是“aa ...... a”。因此,您必须以某种方式区分节点,而不仅仅是“值”。

答案 1 :(得分:1)

  

问:一个讨论显示inorder和preorder遍历都是   必要。有人能解释为什么它们足够了吗?

由于可以唯一从这两次遍历中重构二进制树(或者也可以是顺序和后序),这是一个简单的事实。检查此示例:

  Inorder  : [1,2,3,4,5,6]
  Preorder : [4,2,1,3,5,6]

从预订开始,您知道4是树的根。从inorder开始,您可以确定左侧和右侧子树,然后从这一点开始递归:

                 4
               /   \
  Left subtree       Right subtree
  Inorder : [1,2,3]  Inorder : [5,6]
  Preorder: [2,1,3]  Preorder: [5,6]

在这篇优秀文章中查看更多细节: Reconstructing binary trees from tree traversal。由于结合在一起的树的这两个序列化(遍历实际上将树序列化为字符串)必须对于二叉树是唯一的,所以当且仅当这些遍历是其他两个序列化的子串时,我们得到一个树是另一个树的子树。