我想我已经找到了答案,或者至少是一份传真。
假设树节点已编号,从 1 开始,从上到下、从左到右。假设遍历从根开始,并在找到节点 X 时停止(这意味着父节点链接到其子节点)。另外,为了快速参考,节点 1 到 12 的以 2 为底的对数值为:
log2(1) = 0.0
log2(2) = 1
log2(3) = 1.58
log2(4) = 2
log2(5) = 2.32
log2(6) = 2.58
log2(7) = 2.807
log2(8) = 3
log2(9) = 3.16
log2(10) = 3.32
log2(11) = 3.459
log2(12) = 3.58
Run Code Online (Sandbox Code Playgroud)
小数部分表示唯一的对角线位置(请注意节点 3、6 和 12 的小数部分都是 0.58)。另请注意,每个节点属于树的左侧或右侧,具体取决于对数小数部分是否小于或大于 0.5。抛开轶事不谈,查找节点的算法如下:
因此,举例来说,如果节点 11 是您要查找的节点,那么您首先计算对数 3.459。然后...
通过适当的调整,相同的技术似乎适用于任何平衡的 n 叉树。例如,给定平衡三叉树,以下左边缘、中边缘或右边缘的选择再次基于日志的小数部分,如下所示:
between 0.5-0.832: turn left (a one-third fraction range)
between 0.17-0.49: turn right (another one-third fraction range)
otherwise go down the middle. (the last one-third range)
Run Code Online (Sandbox Code Playgroud)
通过将小数部分乘以 3 而不是 2 来调整算法。同样,为那些想要测试最后一个语句的人提供快速参考:
log3(1) = 0.0
log3(2) = 0.63
log3(3) = 1
log3(4) = 1.26
log3(5) = 1.46
log3(6) = 1.63
log3(7) = 1.77
log3(8) = 1.89
log3(9) = 2
Run Code Online (Sandbox Code Playgroud)
此时我想知道是否有一种更简洁的方式来表达整个“基于日志的自上而下的节点选择”。我很感兴趣,如果有人知道的话...