我正在实现一棵AVL树,并且我试图绕开添加过程的时间复杂性。据我了解,为了达到O(log n),您需要在树节点中保持平衡或高度状态,这样就不必在每次需要它们时都重新计算它们(这可能需要大量的其他树遍历) )。
为解决这个问题,我有一个协议可以递归地“遍历”父指针到根的轨迹,在需要时进行平衡,并在此过程中设置高度。这样,加法算法就具有先“捕获”和“冒泡”的阶段,然后像DOM事件一样备份树。
我的问题是:从技术上讲,这还是O(log n)时间吗?从技术上讲,您只需要处理树中每个级别的一半分割,但是您还需要向下移动,然后每次都向上备份。此操作的确切时间复杂度是多少?
答案 0 :(得分:0)
假设树的高度为H,并且在所有操作期间结构保持平衡。 然后,正如您提到的,插入节点将花费O(H)。
但是,每次将节点添加到AVL树时,都需要一直更新父节点直到根节点的高度。
由于树是平衡的,因此更新高度将仅遍历链接列表式结构,而新插入的节点位于尾部。
可以将高度更新视为等同于遍历长度等于H的链表。 因此,更新高度将花费另一个O(H),总更新时间为2 * O(H),如果我们除去常数因子,则仍为O(log N)。
希望这对您有意义。
答案 1 :(得分:0)
“从技术上讲,您只需要处理树中每个级别的一半的划分,但是您还需要向下移动然后每次都向上备份。此操作的确切时间复杂度是多少?”
您已声明每次必须上下走动。
因此,可以说您的函数的运行时上限为2 * logn。
很明显,这是O(logn)。
更具体地说,我们可以分配常数3和起始值为1,这样
2 * logn <= 3 * logn表示n> = 1的所有值。
这减少到2 <= 3,这当然是正确的。
big-O背后的想法是了解函数的基本形状,当输入大小向无穷大方向移动时,函数的运行时间将达到上限-因此,我们可以将常数因子2降低。