将旧树复制到新树,使用正常的递归方法遍历原树。
由于您要向节点添加新属性,我认为您需要使用新属性的字段构造新节点。
定义一个递归函数来复制以给定节点为根的(子)树。它需要其深度和父级作为输入。 (当然,父节点必须是它在新树中的父节点。)让它返回新(子)树的根。
function copy_node (old_node, new_parent, depth) -> returns new_node {
new_node = new node
new_node.data = old_root.data // whatever that data might be
new_node.depth = depth
new_node.parent = parent
new_node.left = copy_node (old_node.left, new_node, depth + 1)
new_node.right = copy_node (old_node.right, new_node, depth + 1)
return new_node }
复制整棵树
new_tree = copy_node (old_tree, nil, 0)
如果您使用的语言可以随意将字段添加到现有对象,您甚至不必进行额外的复制:
function adorn_node (node, parent, depth) {
node.parent = parent
node.depth = depth
adorn_node (node.left, node, depth + 1)
adorn_node (node.right, node, depth + 1) }
然后开始滚动
adorn_node (root, nil, 0)
话虽如此,您可能会发现大多数二叉树实现不包含这些额外字段是有充分理由的。在您想要在树上执行的许多不同操作中维护它们是很多工作。 深度,尤其是当您需要重新平衡树时,很难保持正确。
而且这些领域通常不会给你买任何东西。大多数对树进行操作的算法都是使用递归函数来实现的,从上面的示例中可以看出,在运行时重新计算 parent 和 depth 非常容易你在树上散步。它们不需要存储在节点本身中。
树平衡通常需要知道左右子树的高度差。 (“depth”是到根的距离;“height”是到子树中最远叶节点的距离。) height 在从根向下的过程中并不那么容易计算,但幸运的是,您通常只对哪个子树具有最大 高度 感兴趣,为此,通常只在每个节点中存储值 -1、0、+1 就足够了。