Algorithm 如何以较低的复杂度计算二叉树的深度?
给定二叉搜索树t,使用递归很容易获得其深度,如下所示:Algorithm 如何以较低的复杂度计算二叉树的深度?,algorithm,binary-search-tree,Algorithm,Binary Search Tree,给定二叉搜索树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(he
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) )
然而,我注意到它的复杂性呈指数级增长,因此当我们有一棵深树时,它的性能会非常差。是否有更快的算法来执行此操作?如果将高度存储为节点对象中的字段,则可以在向树中添加节点时添加1(并在删除过程中进行减法)
这将使操作获得任何节点高度的时间保持不变,但会给添加/删除操作增加一些额外的复杂性 如果将高度存储为节点对象中的字段,则可以在向树中添加节点时添加1(并在删除过程中进行减法)
这将使操作获得任何节点高度的时间保持不变,但会给添加/删除操作增加一些额外的复杂性 这是他在回答中提到的 因此,如果您执行
(1+max(height\u left,height\u right))
,您将不得不访问每个节点,这本质上是一个O(N)操作。对于平衡树的平均情况,您将看到类似于T(n)=2T(n/2)+Θ(1)
现在,如果您可以存储某个节点的高度,则可以将时间改进为O(1)。在这种情况下,树的高度将等于根的高度。因此,您需要对insert(value)
方法进行修改。开始时,根的默认高度为0。要添加的节点的高度指定为0。对于在尝试添加此新节点时遇到的每个节点,如果需要,请将node.height增加1,并确保将其设置为1+max(左侧子节点高度,右侧子节点高度)。因此,height函数将简单地返回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]
这是他在回答中提到的 因此,如果您执行
(1+max(height\u left,height\u right))
,您将不得不访问每个节点,这本质上是一个O(N)操作。对于平衡树的平均情况,您将看到类似于T(n)=2T(n/2)+Θ(1)
现在,如果您可以存储某个节点的高度,则可以将时间改进为O(1)。在这种情况下,树的高度将等于根的高度。因此,您需要对insert(value)
方法进行修改。开始时,根的默认高度为0。要添加的节点的高度指定为0。对于在尝试添加此新节点时遇到的每个节点,如果需要,请将node.height增加1,并确保将其设置为1+max(左侧子节点高度,右侧子节点高度)。因此,height函数将简单地返回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]
树的大小随高度呈指数增长(假设是完全平衡树,则每个后续级别上的节点数是其两倍)。通常,无法避免遍历所有路径,因为您不知道哪条路径可能最高。也就是说,除非你为我们做了一些简化,否则树的大小会随着高度呈指数增长(假设是一棵完全平衡的树,则每个后续级别上的节点数是原来的两倍)。通常,无法避免遍历所有路径,因为您不知道哪条路径可能最高。也就是说,除非你为我们做了一些简化?如果你总是需要读取树中节点的高度,这听起来很聪明,但你必须维护这些值,这意味着你必须覆盖所有树操作来维护高度值。重写,不一定override@cricket_007几乎没有澄清,我试着在我的回答中解决这个问题。在添加节点时简单地添加1可能会被误解。如果以递归方式进行插入,则需要在将节点添加到树后更新高度字段。所以,
height=1+max(左边的孩子的身高,右边的孩子的身高)
应该可以做到这一点,这将是一个固定的时间操作。但是,总的来说,答案不错+1:)如果您总是需要读取树中节点的高度,那么这听起来很聪明,但您必须维护这些值,这意味着您必须覆盖所有树操作以维护高度值。不一定要重写override@cricket_007我试图在我的回答中澄清一点。在添加节点时简单地添加1可能会被误解。如果以递归方式进行插入,则需要在将节点添加到树后更新高度字段。所以,height=1+max(左边的孩子的身高,右边的孩子的身高)
应该可以做到这一点,这将是一个固定的时间操作。但是,总的来说,答案不错+1 :)