我最近听说过三元搜索,我们将一个数组分成3个部分进行比较。这里将进行两次比较,但它将数组减少到n / 3。人们为什么不使用这么多?
答案 0 :(得分:42)
实际上,人们确实将k-ary树用于任意k。
然而,这是一个权衡。要在k-ary树中查找元素,需要大约k * ln(N)/ ln(k)运算(记住基础变化公式)。你的k越大,你需要的整体操作就越多。
你所说的逻辑扩展是“为什么人们不为N个数据元素使用N-ary树?”。当然,这将是一个数组。
答案 1 :(得分:26)
三元搜索仍会为您提供相同的渐近复杂度 O(log N)搜索时间,并增加了实现的复杂性。
可以说同样的论点是为什么你不想要四元搜索或任何其他更高阶。
答案 2 :(得分:25)
搜索10亿(十亿美元 - 1,000,000,000)个分类项目与二元搜索相比平均约为15个,而三元搜索比较大约9个 - 这不是一个巨大的优势。请注意,每次“三元比较”可能涉及2次实际比较。
答案 3 :(得分:9)
哇。我认为,最高投票的答案会错过这个问题。
您的CPU不支持三元逻辑作为单个操作;它将三元逻辑分解为二进制逻辑的几个步骤。 CPU的最佳代码是二进制逻辑。如果芯片很常见,支持三元逻辑作为单一操作,那你就是对的。
B-Trees每个节点可以有多个分支; order-3 B-tree是三元逻辑。树中的每一步都将进行两次比较,而不是一次,这可能会导致CPU时间变慢。
然而,B树很常见。如果你假设树中的每个节点都将分别存储在磁盘上的某个地方,那么你将花费大部分时间从磁盘读取......并且CPU不会成为瓶颈,但磁盘将是。因此,您可以选择每个节点有100,000个子节点的B树,或者几乎不适合一个内存块的任何其他内容。具有这种分支因子的B树很少会超过三个节点,并且您只有三个磁盘读取 - 三个瓶颈位于瓶颈 - 来搜索庞大而庞大的数据集。审阅:
答案 4 :(得分:8)
是什么让你认为三元搜索应该更快?
平均比较次数:
in 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).
所以看起来三元搜索更糟糕。
答案 5 :(得分:8)
三元搜索比二分搜索更快的唯一方法是,如果可以以低于双向比较成本的1.55倍的方式进行3向分区确定。如果项目存储在排序数组中,则3路确定平均为双向确定的1.66倍。但是,如果信息存储在树中,则获取信息的成本相对于实际比较的成本较高,而缓存局部性意味着随机获取一对相关数据的成本并不比获取单个数据的成本差很多。数据,三元树或n路树可以大大提高效率。
答案 6 :(得分:4)
另外,请注意,如果我们继续
,这个序列会推广到线性搜索Binary search
Ternary search
...
...
n-ary search ≡ linear search
因此,在n-ary搜索中,我们将“只有一个比较”,可能需要进行实际的比较。
答案 7 :(得分:2)
“Terinary”(三元?)搜索在最佳情况下更有效,这将涉及搜索第一个元素(或者可能是最后一个元素,具体取决于您首先进行的比较)。对于距离末端较远的元素,首先进行检查,而两次比较会使数组每次缩小2/3,与二分搜索相同的两次比较会使搜索空间缩小3/4。
除此之外,二进制搜索更简单。你只需比较并得到一半或另一半,而不是比较,如果少于得到前三分之一,否则比较,如果少于得到第二个三分之一,否则得到最后三分之一。
答案 8 :(得分:2)
三元搜索可以有效地用于并行架构 - FPGA和ASIC。例如,如果搜索所需的内部FPGA存储器小于FPGA资源的一半,则可以制作重复的存储器块。这将允许同时访问两个不同的存储器地址并在单个时钟周期内进行所有比较。这是100MHz FPGA有时可以胜过4GHz CPU的原因之一:)
答案 9 :(得分:1)
答案 10 :(得分:1)
几乎所有二叉搜索树上的教科书和网站都没有真正谈论二叉树!他们向您展示三元搜索树!真正的二叉树在其叶子中存储数据而不是内部节点(导航键除外)。有些人称这些叶子树,并在教科书中显示节点树之间的区别:
学家Nievergelt,C.-K。 Wong:二叉树总路径长度的上限, 期刊ACM 20(1973)1-6。
以下内容来自Peter Brass关于数据结构的书。
2.1两种搜索树模型
在刚刚给出的大纲中,我们首先强调了一个重要的观点 琐碎的,但实际上它导致了两种不同的搜索树模型 可以与以下大部分材料结合使用,但其中一种材料 是非常可取的。
如果我们在每个节点中将查询键与包含在中的键进行比较 如果查询键较小且右侧分支,则按住左侧分支 如果查询键较大,那么如果它们相等则会发生什么?这两个型号 搜索树的内容如下:
如果查询键小于节点键,则取左分支;否则拿走 右分支,直到你到达树的叶子。内部节点中的键 树只是为了比较;所有的物品都在树叶里。
如果查询键小于节点键,则取左分支;采取正确的分支 如果查询密钥大于节点密钥;并取得包含的对象 如果它们相等,则在节点中。
这一小问题有许多后果:
{在模型1中,底层树是二叉树,而在模型2中,每个 树节点实际上是一个具有特殊中间邻居的三元节点。
{在模型1中,每个内部节点都有一个左子树和一个右子树(每个都可能是一个 树的叶节点),而在模型2中,我们必须允许不完整 节点,左边或右边的子树可能丢失,只有 保证比较对象和密钥存在。
因此,模型1的搜索树的结构比树的结构更规则 模型2;至少对于实施而言,这是一个明显的优势。
{在模型1中,遍历内部节点只需要一次比较, 而在模型2中,我们需要进行两次比较来检查三者 可能性。
实际上,模型1和2中相同高度的树最多包含约 相同数量的对象,但在模型中需要两倍的比较 2到达树的最深处的物体。当然,在模型2中也有 一些早期达到的物体;找到根目录中的对象 只进行了两次比较,但几乎所有物体都在最深处或附近 水平。
定理。高度为h且模型1的树包含最多2 ^ h个对象。 高度为h且模型2的树最多包含2 ^ h + 1 - 1个对象。
这很容易看到,因为高度树h具有左右子树a 高度树最多h - 1,在模型2中另外一个对象 它们。
{在模型1中,内部节点中的键仅用于比较,可能 再次出现在树叶中以识别物体。在模型2中,每个 键只出现一次,与其对象一起出现。
在模型1中甚至可以使用用于比较的键 不属于任何对象,例如,如果该对象已被删除。通过 这在概念上将这些比较和识别功能分开了 这并不奇怪,在以后的结构中我们甚至可能需要定义人工 测试不对应任何对象,只是为了获得良好的搜索划分 空间。用于比较的所有密钥必须是不同的,因为在模型中 1个树,每个内部节点都有非空的左右子树。所以每个关键 最多发生两次,一次作为比较键,一次作为识别键 叶子。
模型2成为首选的教科书版本,因为在大多数教科书中 对象与其键之间的区别不是:关键是对象。 然后在树结构中复制密钥变得不自然。但在 在所有实际应用中,密钥和对象之间的区别非常重要。 人们几乎从不想跟踪一组数字;数字 通常与一些进一步的信息相关联,这通常很多 大于钥匙本身。
答案 11 :(得分:0)
你可能听说过那些涉及称重尺度的谜语的三元搜索。这些尺度可以返回3个答案:左边较轻,两个相同,或左边较重。所以在三元搜索中,只需要进行1次比较。 但是,计算机使用布尔逻辑,它只有2个答案。要进行三元搜索,您实际上必须进行2次比较而不是1次。 我想在某些情况下,这仍然比早期海报提到的更快,但是你可以看到三元搜索并不总是更好,而且在计算机上实现它会更加混乱和不太自然。
答案 12 :(得分:0)
理论上, e 达到k/ln(k)
的最小值,并且由于3比<2>更接近 e ,因此需要较少的比较。您可以检查3/ln(3) = 2.73..
和2/ln(2) = 2.88..
二进制搜索可能更快的原因是它的代码将具有更少的分支并且在现代CPU上运行得更快。
答案 13 :(得分:0)
我刚刚发布了关于三元搜索的blog,我已经展示了一些结果。我还在我的git repo上提供了一些初始级别的实现。我完全同意每一个关于三元搜索的理论部分但是为什么不尝试一下呢?根据实现,如果您有三年的编码经验,该部分很容易。 我发现,如果你拥有庞大的数据集并且你需要多次搜索它,那么三元搜索就有一个优势。 如果您认为通过三元搜索可以做得更好,那就去做吧。
答案 14 :(得分:0)
虽然在两个搜索树中都获得了相同的大O复杂度(ln n),但差异在于常量。您必须在每个级别对三元搜索树进行更多比较。因此,k-ary搜索树的差异可归结为k / ln(k)。这在e = 2.7时具有最小值,并且k = 2提供了最佳结果。