给定二叉搜索树t,使用递归可以很容易地得到它的深度,如下所示:
def node_height(t):
if t.left.value == None and t.right.value == None:
return 1
else:
height_left = t.left.node_height()
height_right = t.right.node_height()
return ( 1 + max(height_left,height_right) )
然而,我注意到它的复杂性呈指数级增长,因此当我们有一棵深树时,它应该表现得非常糟糕。有没有更快的算法呢?
答案 0 :(得分:3)
如果将高度存储为Node对象中的字段,则可以在向树中添加节点时添加1(并在删除期间减去)。
这样可以使操作保持恒定的时间来获取任何节点的高度,但它会在添加/删除操作中增加一些额外的复杂性。
答案 1 :(得分:2)
这种延伸来自他在答案中提到的@cricket_007。
因此,如果您执行( 1 + max(height_left,height_right) )
,则最终必须访问每个节点,这实际上是一个O(N)操作。对于具有平衡树的平均情况,您会看到类似T(n) = 2T(n/2) + Θ(1)
的内容。
现在,如果您可以存储某个节点的高度,则可以将其改进为O(1)的时间。在这种情况下,树的高度将等于根的高度。因此,您需要进行的修改将是您的insert(value)
方法。在开始时,根的默认高度为0.要添加的节点的高度为0.对于尝试添加此新节点时遇到的每个节点,如果需要,请将node.height增加1,并确保它被设置为1 + max(左孩子的身高,右孩子的身高)。因此,高度函数将简单地返回node.height,因此允许恒定时间。插入物的时间复杂度也不会改变;我们只需要一些额外的空间来存储n
整数值,其中n
是节点数。
以下内容旨在让我们了解我想说的内容。
5 [0]
- insert 2 [increase height of root by 1]
5 [1]
/
/
[0] 2
- insert 1 [increase height of node 2 by 1, increase height of node 5 by 1]
5 [2]
/
/
[1] 2
/
/
[0] 1
- insert 3 [new height of node 2 = 1 + max(height of node 1, height of node 3)
= 1 + 0 = 1; height of node 5 also does not change]
5 [2]
/
/
[1] 2
/ \
/ \
[0] 1 3 [0]
- insert 6 [new height of node 5 = 1 + max(height of node 2, height of node 6)
= 1 + 1 = 2]
5 [2]
/ \
/ \
[1] 2 6 [0]
/ \
/ \
[0] 1 3 [0]