无需制作 a 的完整副本Set
即可将元素插入其中。在内部,元素存储在树中,这意味着您只需要沿插入路径创建新节点。未触及的节点可以在Set
. 正如Deitrich Epp所指出的,在平衡树O(log(n))
中是插入路径的长度。(很抱歉忽略了这个重要的事实。)
假设您的Tree
类型如下所示:
data Tree a = Node a (Tree a) (Tree a)
| Leaf
...并说你有一个Tree
看起来像这样的
let t = Node 10 tl (Node 15 Leaf tr')
...在哪里tl
和tr'
是一些命名的子树。现在说你想插入12
这棵树。好吧,看起来像这样:
let t' = Node 10 tl (Node 15 (Node 12 Leaf Leaf) tr')
子树tl
and在andtr'
之间共享,您只需要构造 3 个 new即可,即使 的大小可能远大于 3。t
t'
Nodes
t
编辑:再平衡
关于再平衡,请这样想,并注意我在这里并不严谨。假设你有一棵空树。已经平衡了!现在说你插入一个元素。已经平衡了!现在假设您插入另一个元素。嗯,有一个奇数,所以你不能在那里做很多事情。
这是棘手的部分。假设您插入另一个元素。这可以有两种方式:向左或向右;平衡或不平衡。在不平衡的情况下,您可以清楚地执行树的旋转来平衡它。在它平衡的情况下,已经平衡了!
这里需要注意的重要一点是,您一直在重新平衡。这不像你有一棵树,决定插入一个元素,但在你这样做之前,你重新平衡,然后在你完成插入后留下一团糟。
现在说你继续插入元素。树会变得不平衡,但不会太多。当这种情况发生时,首先你要立即纠正它,其次,纠正发生在插入的路径上,它O(log(n))
位于平衡树中。您链接到的论文中的旋转最多接触树中的三个节点以执行旋转。所以你在O(3 * log(n))
重新平衡时正在工作。那还是O(log(n))
。