Algorithm naï的时间复杂度;两个二叉搜索树的ve合并

Algorithm naï的时间复杂度;两个二叉搜索树的ve合并,algorithm,merge,time-complexity,binary-search-tree,asymptotic-complexity,Algorithm,Merge,Time Complexity,Binary Search Tree,Asymptotic Complexity,我看到了一个非常简短的合并两个二进制搜索树的算法。我很惊讶这是多么简单,而且效率也很低。但当我试图猜测它的时间复杂性时,我失败了 让我们有一个包含整数的两个不可变的二进制搜索树(非平衡),您希望使用以下伪代码递归算法将它们合并在一起。功能insert是辅助功能: function insert(Tree t, int elem) returns Tree: if elem < t.elem: return new Tree(t.elem, insert(t.left

我看到了一个非常简短的合并两个二进制搜索树的算法。我很惊讶这是多么简单,而且效率也很低。但当我试图猜测它的时间复杂性时,我失败了

让我们有一个包含整数的两个不可变的二进制搜索树(非平衡),您希望使用以下伪代码递归算法将它们合并在一起。功能
insert
是辅助功能:

function insert(Tree t, int elem) returns Tree:
    if elem < t.elem:
        return new Tree(t.elem, insert(t.leftSubtree, elem), t.rightSubtree)
    elseif elem > t.elem:
        return new Tree(t.elem, t.leftSubtree, insert(t.rightSubtree, elem))
    else
        return t

function merge(Tree t1, Tree t2) returns Tree:
    if t1 or t2 is Empty:
        return chooseNonEmpty(t1, t2)
    else
        return insert(merge(merge(t1.leftSubtree, t1.rightSubtree), t2), t1.elem)
函数插入(树t,int元素)返回树:
如果elemt.elem:
返回新树(t.elem,t.leftSubtree,insert(t.righsubtree,elem))
其他的
返回t
函数merge(树t1,树t2)返回树:
如果t1或t2为空:
返回选择空(t1、t2)
其他的
返回insert(merge(merge(t1.leftSubtree,t1.righsubtree),t2),t1.elem)

我想这是一个指数算法,但我找不到一个论点。此合并算法最糟糕的时间复杂度是什么?

精确计算非常困难,但在最糟糕的情况下,它似乎不是多项式有界的(这不是一个完整的证明,但是,您需要一个更好的证明):

  • insert最糟糕的情况是复杂性
    O(h)
    ,其中
    h
    是树的高度(即至少
    log(n)
    ,可能
    n

  • merge()的复杂性可以是这样的:
    T(n1,n2)=O(h)+T(n1/2,n1/2)+T(n1-1,n2)

  • <> LI> < P> >考虑<代码> f(n)< /代码>,使<代码> f(1)=t(1, 1)和<代码> f(n+1)=log(n)+f(n/2)+f(n-1)< /代码>。我们可能可以证明
    F(n)
    小于
    T(n,n)
    (因为
    F(n+1)
    包含
    T(n,n)
    ,而不是
    T(n,n+1)

  • 我们有
    F(n)/F(n-1)=log(n)/F(n-1)+F(n/2)/F(n-1)+1

  • 对于某些
    k
    ,假设
    F(n)=θ(n^k)
    。然后
    F(n/2)/F(n-1)>=a/2^k
    对于某些
    a>0
    (来自
    Theta
    中的常数)

  • 这意味着(超过某一点)对于某些固定的ε0,我们总是有ε=1+ε,这与εn=O(n^k)不相容,因此存在矛盾

  • 所以对于任何
    k
    ,F(n)不是
    Theta(n^k)
    。直观地看,您可以看到问题可能不是
    Omega
    部分,而是
    big-O
    部分,因此它可能不是
    O(n)
    (但从技术上讲,我们在这里使用
    Omega
    部分来获得
    a
    )。由于
    T(n,n)
    应该比
    F(n)
    更大,
    T(n,n)
    不应该是多项式,可能是指数的

但又一次,这根本不严谨,所以也许我真的错了…

让我们考虑最坏的情况:

在每个阶段,每个树都处于最大不平衡状态,即每个节点至少有一个子树大小为1

在这种极端情况下,
insert
的复杂性很容易显示为
}(n)
,其中
n
是树中的元素数,因为高度为
~n/2


基于上述约束,我们可以推导出
合并
的时间复杂度的递推关系:

其中
n,m
t1,t2
的大小。在不丧失一般性的情况下,假定右子树始终包含单个元素。这些术语对应于:

  • T(n-2,1)
    :对
    t1的子树上的
    merge
    的内部调用
  • T(n-1,m)
    :对
    t2上的
    merge
    的外部调用
  • ㄈ(n+m)
    :最后一次调用
    insert

为了解决这个问题,让我们重新替换第一项并观察一个模式:

我们可以通过去掉第一项来解决这个问题:

其中,在步骤
(*)
中,我们使用了变量替换的变化
i->i+1
。当
k=n
时,递归停止:

T(1,m)
只是将一个元素插入到一个大小为
m
的树中,这在我们假设的设置中显然是
ㄉ(m)

因此,
merge
的绝对最坏情况时间复杂度为


注:

  • 参数的顺序很重要。因此,通常将较小的树插入较大的树(从某种意义上说)
  • 实际上,在程序的每个阶段,都不可能有最大不平衡的树。一般情况下,自然会涉及半平衡树
  • 最佳情况(即始终完全平衡的树)要复杂得多(我不确定是否存在类似上述的分析解决方案;请参见
    gdelab
    的答案)

编辑:如何计算指数和

假设我们要计算总和:

其中
a、b、c、n
为正常数。在第二步中,我们将基数改为
e
(自然指数常数)。通过这种替换,我们可以将
lnc
视为变量
x
,区分与其相关的几何级数,然后设置
x=lnc

但几何级数有一个封闭形式的解(一个不难推导的标准公式):

因此,我们可以根据
x
将这个结果区分
n
次,得到
Sn
的表达式。对于上述问题,我们只需要前两种权力:

因此,麻烦的术语是:

这正是Wolfram Alpha