You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用unittest测试红黑树时如何忽略嵌套结构的parent字段?

解决红黑树测试中循环引用导致的递归错误问题

问题根源

你猜的没错,dataclass默认的__eq__方法会递归对比所有属性,而Node的parent属性形成了循环引用(父节点指向子节点,子节点又指向父节点),导致self.assertEqual(tree, expected_tree)执行时无限递归,最终触发RecursionError。

解决办法

方法1:自定义Node的__eq__方法,忽略parent属性

直接修改Node类,重写__eq__方法,只对比color、value、left、right这些核心属性,跳过parent:

@dataclass
class Node(Generic[T]):
    color: Color
    value: T
    parent: Optional['Node[T]'] = None
    left: Optional['Node[T]'] = None
    right: Optional['Node[T]'] = None

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Node):
            return False
        # 只比较关键属性,不处理parent
        return (self.color == other.color
                and self.value == other.value
                and self.left == other.left
                and self.right == other.right)

这样dataclass生成的默认__eq__会被覆盖,对比时不会递归处理parent,自然避免循环引用问题。

方法2:测试时手动遍历验证结构,不直接对比整个树

如果不想修改Node类的默认行为,可以在测试里写一个遍历函数,逐个验证节点的核心属性,替代self.assertEqual(tree, expected_tree):

def _compare_nodes(self, actual: Optional[Node], expected: Optional[Node]):
    if actual is None and expected is None:
        return
    self.assertIsNotNone(actual)
    self.assertIsNotNone(expected)
    self.assertEqual(actual.color, expected.color)
    self.assertEqual(actual.value, expected.value)
    # 递归对比左右子节点,不涉及parent
    self._compare_nodes(actual.left, expected.left)
    self._compare_nodes(actual.right, expected.right)

def test_left_rotation(self):
    # ... 原有测试代码 ...

    # 替换原来的self.assertEqual(tree, expected_tree)
    self._compare_nodes(tree.root, expected_tree.root)

这种方式完全由你控制验证内容,既能避开循环引用,也能精准检查树的结构。

方法3:给dataclass加eq=False,自定义树的对比逻辑

给Node和RedBlackTree添加eq=False参数,然后手动实现树的__eq__方法:

@dataclass(eq=False)
class Node(Generic[T]):
    color: Color
    value: T
    parent: Optional['Node[T]'] = None
    left: Optional['Node[T]'] = None
    right: Optional['Node[T]'] = None

@dataclass(eq=False)
class RedBlackTree(Generic[T]):
    root: Node

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, RedBlackTree):
            return False
        # 自定义节点对比逻辑,跳过parent
        def compare_nodes(a: Optional[Node], b: Optional[Node]) -> bool:
            if a is None and b is None:
                return True
            if a is None or b is None:
                return False
            return (a.color == b.color
                    and a.value == b.value
                    and compare_nodes(a.left, b.left)
                    and compare_nodes(a.right, b.right))
        return compare_nodes(self.root, other.root)

这样树的对比会按你写的逻辑执行,不会触发循环递归。

额外建议

测试红黑树时,可以单独验证parent属性的正确性:比如遍历每个节点,检查子节点的parent是否指向正确的父节点。这样既避开了循环对比,又能确保父子关系无误。

内容的提问来源于stack exchange,提问作者udduu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 21:22:35