如何合并两个维护BST属性的二叉搜索树?
如果我们决定从树中获取每个元素并将其插入到另一个树中,则此方法的复杂性为O(n1 * log(n2))
,其中n1
是树的节点数(例如{ {1}}),我们已经拆分了,T1
是另一棵树的节点数(比如n2
)。在此操作之后,只有一个BST具有T2
个节点。
我的问题是:我们可以做得比O(n1 * log(n2))更好吗?
答案 0 :(得分:26)
Naaff回答了一些细节:
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)
答案 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使用两个辅助堆栈。由于我们需要以排序的形式打印元素,因此每当我们从任何树中获取较小的元素时,我们就会打印它。如果元素更大,那么我们将它推回到堆栈以进行下一次迭代。