更新:有关此联接操作不正确性的更新,请参见下文
这是一个可能的解决方案的粗略草图:
我认为我可以使用一种随机平衡的B +树来解决此问题。就像开挖一样,这些树具有独特的表现形式。与挖掘不同,它们多次存储一些密钥。可能有可能通过使用Bent等人的“偏爱的搜索树”中的技巧来解决,该技巧仅将每个关键字存储在它出现的最高(即最接近根)级别中。
通过首先将每个值与比特流相关联来创建用于有序唯一值集的树,类似于将treap中的每个值与优先级相关联的方式。树中的每个节点都包含密钥和位流。此外,非叶节点还包含一个自然数,该自然数指示以该节点为根的树的高度。内部节点可以具有任何非零数量的子代。像B +树一样,从根到叶的每个非自相交路径都具有相同的长度。
每个内部节点包含(如在B +-树中)其后代叶子的最大密钥。每一个还包含一个自然数,该自然数指示以为根的树的高度,以及从第个比特开始与关联的比特流。如果以为根的树中的每个键在其位流中都具有相同的第一位,则每个子代都是叶子,而为。否则,的子级是内部节点,所有内部节点在与它们的键关联的位流中都具有相同的第位。k i v k i + 1 v v i 1 v ivķ一世vķ我+ 1vv一世1个v一世
要从具有相关位流的键排序列表中创建树,请首先根据键流中的第一位将键收集到连续的组中。对于这些组中的每个组,使用该组中最大密钥的密钥和位流创建父对象,但忽略流的第一位。现在,对新父母执行相同的分组过程以创建祖父母。继续直到仅剩一个节点为止;这是树的根。
以下密钥和(开头)位流的列表由其下方的树表示。在位流前缀中,“。” 意味着一点。即,假设没有其他键的位流是不同的,则首先具有0的键A的任何位流都将产生与其他树相同的树。
A 0...
B 00..
C 10..
D 0...
E 0011
F 1...
G 110.
H 0001
____H____
/ \
E H
| / \
__E__ G H
/ | \ | |
B C E G H
/ \ | / \ / \ |
A B C D E F G H
特定内部节点的每个子节点在其位流的第一位都具有相同的位。这称为父级的“颜色”-0是红色,1是绿色。这个孩子有一个“味道”,这取决于它的位流的第一位-0是樱桃,1是薄荷。叶子有味道,但没有颜色。根据定义,樱桃节点不能有绿色的父节点,而薄荷节点不能有红色的父节点。
假设比特流中的比特为均匀分布的IID,则节点的父节点数目的PMF 为
,期望值为。对于所有,这都是,因此预期的树高为。2 1 − n ( n − 1ñ21 − n ( n − 1i − 1)(Ñ + 1 )/ 2Ñ ≥ 2≤ 34ñØ (LGn )
要连接两棵等高的树,请首先检查其根是否具有相同的颜色。如果是这样,请从其最左边的子节点的左根断开,并从其最左边的子节点的右根断开,然后递归连接这两个树。结果将是一棵高度相同或更高的树,因为它们具有相同的风味(请参见下文)。如果递归连接两棵树的结果与两个被切断的子代的高度相同,则使其成为根的中间子代,剩余的左根子代在它的前面,而剩余的右根子代在它的后面。如果将其高1,则将其子节点设为根的中间子节点,将其左根的剩余子节点置于其前,将其右根的剩余子节点置于其后。如果根的颜色不同,请检查其味道是否相同。如果有的话 给他们一个新的父级,并带有右根的密钥和位流,以消除其第一位。如果不是,请给每个根节点一个新的父节点,并使用旧根节点的密钥和位流(将每个第一位都消除),然后递归地加入这些树。
此算法中有两个递归调用。第一种是当根的颜色相同时,第二种是当根的颜色和口味不同时。根具有相同的颜色,概率为。在这种情况下,递归调用总是看到具有相同味道的根,因此第二种递归永远不会在第一种之后发生。但是,第一个可以重复发生,但每次发生的概率为,因此预期运行时间仍为。第二个递归调用以概率发生,并且随后的递归调用始终在具有不同颜色的树上,因此适用相同的分析。1 / 21 / 2O (1 )1 / 4
要连接两棵不等高的树,请首先沿着右树的左脊进行追踪,假设右树更高。(另一种情况是对称的。)当到达两棵等高的树时,对两棵等高的树执行联接操作,修改如下:如果结果具有相同的高度,则用结果替换子树加入。如果结果更高,则在通过添加根的父级使树高一个之后,将树的父级连接到另一棵树的根的右侧。树的高度等于,因此树的高度相同,因此终止于期望的。
1 / 2O (1 )
更新:感谢QuickCheck,我发现上面的join方法不会产生与上面唯一表示的树相同的树。问题在于,叶子附近的父母选择可能会根据可用的同胞而改变。要解决这些更改,join必须一直遍历所有叶子,而不是。这是找到的示例QuickCheck:O (1 )
a 01110
b 110..
c 10...
d 00000
由制成的树的[a,b]
高度为2,由制成的树的[c,d]
高度为2,由制成的树的joinEqual (tree [a,b]) (tree [c,d])
高度为3。但是,由制成的树的[a,b,c,d]
高度为5。
这是我用来发现此错误的代码。