假设我有两个AVL树,并且我知道它们各自的大小。但是,我不知道是否有重复的节点或任何其他信息。在新的AVL树中合并它们的最有效方法是什么?原始树木可以被摧毁。
答案 0 :(得分:5)
T1
和T2
转换为已排序的列表L1
和L2
L1
和L2
合并到排序列表L
L
转换为树T
。如果您对AVL树的表示允许有效地迭代它们(例如,使用后退,延续,延迟评估等),您应该能够在没有中间列表的情况下进行迭代。
更新:由于您的编程语言似乎是C / C ++,您可能会暂时将您的AVL节点结构滥用为链接列表中的节点,然后再次将其重新用于输出树。
更新2 :@hwlau:这是O(N),我已经使用avl.pl中提供的Prolog中我自己的AVL实现和此测试程序avl_test.pl进行了检查在合并大小为1,2,4,8,16 ......的AVL树时检查操作次数。
这是输出:
timing avl_merge, size: 128
% 1,790 inferences, 0.000 CPU in 0.001 seconds (0% CPU, Infinite Lips)
timing avl_merge, size: 256
% 3,591 inferences, 0.010 CPU in 0.002 seconds (430% CPU, 359100 Lips)
timing avl_merge, size: 512
% 7,176 inferences, 0.030 CPU in 0.028 seconds (107% CPU, 239200 Lips)
...
timing avl_merge, size: 32000
% 451,839 inferences, 0.490 CPU in 0.499 seconds (98% CPU, 922120 Lips)
timing avl_merge, size: 64000
% 903,682 inferences, 0.900 CPU in 0.964 seconds (93% CPU, 1004091 Lips)
timing avl_merge, size: 128000
% 1,807,363 inferences, 2.420 CPU in 2.559 seconds (95% CPU, 746844 Lips)
很明显,推理/操作的数量与合并树的大小成正比,因此算法的复杂度为O(N)。
答案 1 :(得分:2)
它不是最有效的,但绝对是最容易实现的。您只需将第二个树中的所有节点添加到第一个树。您无需从第二个树中删除节点。您只需销毁第二棵树,然后将第一棵树作为结果。时间复杂度为O(N*log(N))
。