最近我听说了三分查找,它将一个数组分成三部分并进行比较。这里会有两次比较,但它可以将数组缩小到 n/3 的规模。为什么人们不经常使用它呢?
最近我听说了三分查找,它将一个数组分成三部分并进行比较。这里会有两次比较,但它可以将数组缩小到 n/3 的规模。为什么人们不经常使用它呢?
实际上,人们确实使用 k 叉树来处理任意的 k 值。
然而,这是一种权衡。
要在 k 叉树中查找一个元素,你需要大约 k*ln(N)/ln(k) 次操作(记住换底公式)。k 越大,总体操作次数就越多。
你所说的逻辑延伸是 "为什么不用一个 N 叉树来处理 N 个数据元素?"。当然,这将是一个数组。
k/ln(k)
的最小值出现在 k=e
(即 k=2.71
),因此“最优”的 k
叉树是 e
叉树。 二叉树非常接近 e
叉树。 - Andras Nemeth三分查找仍将给您相同的渐近复杂度O(log N)搜索时间,同时增加了实现的复杂性。
相同的论点也适用于为什么您不想要四分查找或任何其他高阶。
对于10亿(美国十亿 - 1,000,000,000)个已排序的项目进行搜索,使用二分查找平均需要约15次比较,而三分查找则需要约9次比较 - 这并没有太大的优势。请注意,“三分比较”中每个可能包含2次实际比较。
哇,排名最高的答案在这方面错了,我觉得。
你的CPU不支持三进制逻辑作为单个操作;它将三进制逻辑分解成几步二进制逻辑。对于CPU来说,最优的代码是二进制逻辑。如果常见芯片支持三进制逻辑作为单个操作,那么你就是对的。
B树可以在每个节点上有多个分支;一个3阶B树是三进制逻辑。每向下一层,需要进行2次比较而不是1次,这可能会导致它在CPU时间上变慢。
然而,B树非常普遍。如果您假定树中的每个节点都将单独存储在磁盘的某个地方,那么大部分时间都将用于从磁盘读取数据... CPU不会成为瓶颈,但磁盘会成为瓶颈。因此,您采用具有100,000个子节点的B树,或者任何其他仅刚好适合一个内存块的大小。具有这种分支因子的B树很少会超过三个节点高,并且您只需要三次磁盘读取 - 三次停留在瓶颈处 - 就可以搜索巨大的数据集。
回顾:
JB
,如果大于则向右跳转JA
,如果相等则向下跳转JE
)。二叉树具有两种跳转操作(如果小于则向左跳转JB
,如果大于则向右跳转JA
)。处理器是否具有二进制或三进制架构与此无关。只与IA-32架构上的指令JA
、JB
和JE
有关。 - Abelin ternary search = ((1/3)*1 + (2/3)*2) * ln(n)/ln(3) ~ 1.517*ln(n)
in binary search = 1 * ln(n)/ln(2) ~ 1.443*ln(n).
最坏的比较次数:
in ternary search = 2 * ln(n)/ln(3) ~ 1.820*ln(n)
in binary search = 1 * ln(n)/ln(2) ~ 1.443*ln(n).
看起来三分搜索更糟糕。
2 * log(n)/log3
?我在一个层级里并不总是需要进行两次比较。例如,如果我有 [..a..b..]
,并且 x < a
成立,那么就没有必要与 b
进行比较了。 - LazerBinary search
Ternary search
...
...
n-ary search ≡ linear search
e
在理论上是最经济的基数,尽管在硬件上实际执行仍然是一个问题。因此,在我们拥有支持硬件级别三元逻辑的机器之前,二进制是唯一的选择。 - Lazer如果查询键小于节点键,则走左分支;否则,走右分支,直到到达树的叶子节点。树内部的键仅用于比较;所有对象都在叶子节点中。
如果查询键小于节点键,则走左分支;如果查询键大于节点键,则走右分支;如果相等,则取包含在节点中的对象。
这个细节有许多后果:
{ 在模型 1 中,底层树是二叉树,而在模型 2 中,每个树节点实际上是一个三元节点,具有特殊的中间邻居。
{ 在模型 1 中,每个内部节点都有左子树和右子树(可能是树的叶节点),而在模型 2 中,我们必须允许不完整的节点,其中左或右子树可能丢失,并且仅保证存在比较对象和键。
所以,模型 1 的搜索树结构比模型 2 更加规则;至少对于实现来说,这是一个明显的优势。
在模型1中,遍历内部节点只需要进行一次比较,而在模型2中,我们需要进行两次比较来检查三种可能性。