判断一颗树是不是另一棵树的子结构

本文介绍了一种算法,用于判断一棵二叉树B是否为另一棵二叉树A的子结构。首先需要找到A中与B根节点相同的节点,然后递归检查B的剩余节点是否能在A中一一对应。通过两个递归函数实现此过程。

问题

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路及实现

首先要明确的一点是,子结构不是子树,子树是一个更强的条件,而子结构只是指树结构中有这一子部分,如下图,B不是A的子树,但却是A的子结构。

	     1         2
        / \         \
       2   3         5
      /	\ 	\
     4   5   6
       (A)       (B)

所以思路就是,
(1) 先从A找到一个节点与B的根节点相同;
(2) 然后再比较B剩下的节点是否与A的一一对应。
可以用递归的方法实现,这第二步有点像判断两颗树是否相等,只不过这里只是子结构,不要求全部节点相同。
我们先实现第二步:

    bool isSubtree(TreeNode* pRoot1, TreeNode* pRoot2){
        // pRoot2到终点了,还没找到与pRoot1不一样的点,返回真
        if(pRoot2 == NULL) return true;
        // pRoot2还没到终点,pRoot1先到终点了,返回false
        if(pRoot1 == NULL) return false;
        if(pRoot1->val != pRoot2-> val) return false;
        return isSubtree(pRoot1->left, pRoot2->left) 
            && isSubtree(pRoot1->right, pRoot2->right);
    }

第一步也可以用递归实现:
先从根节点调用isSubtree,若不成立,则判断其左子树和右子树。

    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot2 == NULL || pRoot1 == NULL) return false;
        return isSubtree(pRoot1, pRoot2)
            || HasSubtree(pRoot1->left, pRoot2) 
            || HasSubtree(pRoot1->right, pRoot2);
    }
### 验证一棵树是否满足红黑的特性 要验证一棵树是否符合红黑的性质,需逐一检查红黑的核心规则。以下是详细的验证方法: #### 1. **根节点的颜色** 红黑的第一个规则是:**根节点必须是黑色**。 可以通过简单的颜色属性检查来确认这一点。 ```python def is_root_black(root): return root.color == "black" ``` 如果根节点不符合这一条件,则这棵不满足红黑的定义[^1]。 --- #### 2. **每个节点的孩子节点颜色约束** 第二个重要规则是:**任何红色节点的两个孩子都不能同时为红色**(即不存在连续的红色节点)。这意味着每条路径上的任意两个相邻节点不能同时为红色。 通过递归遍历整棵可以实现这一验证逻辑: ```python def no_consecutive_reds(node): if node is None: return True if node.color == "red": if (node.left and node.left.color == "red") or \ (node.right and node.right.color == "red"): return False return no_consecutive_reds(node.left) and no_consecutive_reds(node.right) ``` 如果发现有任何一条路径上存在连续的红色节点,则说明该不符合红黑的性质[^4]。 --- #### 3. **叶子节点统一为黑色** 第三个规则规定:**所有的叶子节点(NIL节点)都应该是黑色**。这是为了确保的整体结构能够维持平衡状态。 可以在遍历时额外检查所有叶节点的颜色属性是否均为黑色: ```python def are_leaves_black(node): if node is None: return True if not node.left and not node.right: # 叶子节点 return node.color == "black" return are_leaves_black(node.left) and are_leaves_black(node.right) ``` 如果任何一个叶子节点不是黑色,则该无法视为合法的红黑[^1]。 --- #### 4. **相同路径上的黑色节点数一致** 第四个核心规则涉及路径长度一致性:**从任一给定节点出发到达其后代 NIL 节点的所有简单路径,均包含相同数量的黑色节点**。这种一致性对于保证时间复杂度至关重要。 为此,需要计算并比较各路径上的黑色节点计数: ```python def count_black_nodes(node, current_count=0): if node is None: return current_count black_count_left = count_black_nodes(node.left, current_count + (1 if node.color == "black" else 0)) black_count_right = count_black_nodes(node.right, current_count + (1 if node.color == "black" else 0)) if black_count_left != black_count_right: raise ValueError("Paths do not have the same number of black nodes.") return black_count_left ``` 若某条路径上的黑色节点数目与其他路径不符,则表明该违背了红黑的关键规则之一[^5]。 --- #### 综合验证函数 最终,将上述几个部分组合成一个完整的验证程序如下所示: ```python class Node: def __init__(self, color="black", left=None, right=None): self.color = color self.left = left self.right = right def validate_rb_tree(root): if not is_root_black(root): # 检查根节点是否为黑色 return False try: _ = count_black_nodes(root) # 检查路径上的黑色节点数是否一致 except ValueError: return False if not no_consecutive_reds(root): # 检查是否存在连续红色节点 return False if not are_leaves_black(root): # 检查叶子节点是否全部为黑色 return False return True ``` 调用 `validate_rb_tree` 函数即可判定输入是否完全遵循红黑的所有性质。 --- ### 结论 只有当以上四条规则都被严格遵守时,才能断言一棵树确实属于红黑范畴[^4][^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值