如何有效地合并两个BST?

时间:2009-06-17 17:35:44

标签: c++ algorithm data-structures merge binary-search-tree

如何合并两个维护BST属性的二叉搜索树?

如果我们决定从树中获取每个元素并将其插入到另一个树中,则此方法的复杂性为O(n1 * log(n2)),其中n1是树的节点数(例如{ {1}}),我们已经拆分了,T1是另一棵树的节点数(比如n2)。在此操作之后,只有一个BST具有T2个节点。

我的问题是:我们可以做得比O(n1 * log(n2))更好吗?

6 个答案:

答案 0 :(得分:26)

Naaff回答了一些细节:

  • 将BST展平为排序列表为O(N)
    • 这只是对整棵树的“有序”迭代。
    • 两者都是O(n1 + n2)
  • 将两个排序列表合并为一个排序列表为O(n1 + n2)。
    • 保持指向两个列表头部的指示
    • 选择较小的头部并使其指针前进
    • 这是合并排序合并的方式
  • 从排序列表中创建完美平衡的BST是O(N)
    • 请参阅下面的算法[1]
    • 的代码段
    • 在我们的例子中,排序列表的大小为n1 + n2。所以O(n1 + n2)
    • 生成的树将是二进制搜索列表的概念BST

O(n1 + n2)的三个步骤导致O(n1 + n2)

对于相同数量级的n1和n2,它优于O(n1 * log(n2))

[1]从排序列表创建平衡BST的算法(在Python中):

def create_balanced_search_tree(iterator, n):
    if n == 0:
        return None
    n_left = n//2
    n_right = n - 1 - n_left
    left = create_balanced_search_tree(iterator, n_left)
    node = iterator.next()
    right = create_balanced_search_tree(iterator, n_right)
    return {'left': left, 'node': node, 'right': right}

答案 1 :(得分:19)

  • 将树状展平为已排序的列表。
  • 合并已排序的列表。
  • 从合并列表中创建树。
IIRC,即O(n1 + n2)。

答案 2 :(得分:8)

如何将两个树展平为排序列表,合并列表然后创建新树?

答案 3 :(得分:1)

乔纳森,

排序后,我们有一个长度为n1 + n2的列表。从中构建二叉树将花费log(n1 + n2)时间。这与合并排序相同,只是在每个递归步骤中我们没有像合并排序算法那样的O(n1 + n2)项。所以时间复杂度是log(n1 + n2)。

现在整个问题的复杂性是O(n1 + n2)。

另外我会说如果两个列表的大小相当,这种方法很好。如果大小不可比,那么最好将小树的每个节点插入一棵大树中。这将花费O(n1 * log(n2))时间。 例如,如果我们有两个大小为10的树,另一个大小为1024的树。 这里n1 + n2 = 1034,其中n1log(n2)= 10 * 10 = 100。 因此,方法必须取决于两棵树的大小。

答案 4 :(得分:0)

O(n1 * log(n2))是平均情况,即使我们将2个未排序的列表合并到BST中也是如此。我们没有利用列表是排序列表或BST的事实。

据我说 让我们假设一个BST有n1个元素而另一个有n2个元素。 现在将一个BST转换为O(n1)中的排序数组列表L1。

合并BST(BST,数组)

if(Array.size == 0)返回BST if(Array.size == 1) 在BST中插入元素。返回BST;

在数组中找到左边元素< BST.rootnode和右元素> = BST.rootnode说索引。 if(BST.rootNode.leftNode == null)//没有左边的节点 {   将所有数组从Index插入0到BST的左边  } 其他 {  合并BST(BST.leftNode,Array {0 to Index}) }

if(BST.rootNode.rightNode == null)//即没有正确的节点 {   将Index中的所有数组插入到BST右侧的Array.size中  } 其他 {  合并BST(BST.rightNode,Array {Index to Array.size}) }

返回BST。

此算法将采用<<每次我们分区数组和BST来处理子问题时,时间比O(n1 * log(n2))。


答案 5 :(得分:-1)

这个想法是使用迭代的顺序遍历。我们为两个BST使用两个辅助堆栈。由于我们需要以排序的形式打印元素,因此每当我们从任何树中获取较小的元素时,我们就会打印它。如果元素更大,那么我们将它推回到堆栈以进行下一次迭代。