Performance 非均匀分布的二进制搜索
对于均匀分布,二进制搜索是高效的。列表中的每个成员都有相同的“命中”概率。这就是为什么你每次都去中心Performance 非均匀分布的二进制搜索,performance,algorithm,binary-search,Performance,Algorithm,Binary Search,对于均匀分布,二进制搜索是高效的。列表中的每个成员都有相同的“命中”概率。这就是为什么你每次都去中心 对于非均匀分布是否有有效的算法?e、 g.一个1/x分布之后的分布。让我精确一点。二进制搜索所需的是: Given array A which is sorted, but have non-uniform distribution Given left & right index L & R of search range Want to search for a val
对于非均匀分布是否有有效的算法?e、 g.一个1/x分布之后的分布。让我精确一点。二进制搜索所需的是:
Given array A which is sorted, but have non-uniform distribution
Given left & right index L & R of search range
Want to search for a value X in A
To apply binary search, we want to find the index M in [L,R]
as the next position to look at.
Where the value X should have equal chances to be in either range [L,M-1] or [M+1,R]
一般来说,您当然希望在您认为X值应该在A中的位置选择M。
因为即使你错过了,总“机会”的一半也会被消除
所以在我看来,你对分销有一些期望。
如果你能告诉我们“1/x分布”的确切含义,那么
也许这里有人可以根据我的建议为你提供帮助
让我举一个有效的例子 我将使用与@Leonid Volnitsky类似的“1/x分布”解释 下面是生成输入数组
a
from random import uniform
# Generating input
a,b = 10,20
A = [ 1.0/uniform(a,b) for i in range(10) ]
A.sort()
# example input (rounded)
# A = [0.0513, 0.0552, 0.0562, 0.0574, 0.0576, 0.0602, 0.0616, 0.0721, 0.0728, 0.0880]
假设要搜索的值为:
X = 0.0553
那么X的估计指数为:
= total number of items * cummulative probability distribution up to X
= length(A) * P(x <= X)
因此
嗯,这是非常准确的
要重复预测X在A的每个给定部分中的位置的过程,需要更多的工作。但我希望这足以说明我的想法
我知道这个可能不再像是二进制搜索了
如果你能在一步之内得到接近的答案。
但是请承认,如果您知道输入数组的分布,这就是您可以做的。二进制搜索的目的是,对于已排序的数组,每次将数组减半时,您都在最小化最坏情况,例如,您可以执行的最坏检查数是log2(条目)。如果您执行某种“不均匀”的二进制搜索,将数组分为更小和更大的一半,如果元素始终位于更大的一半,则可能会出现更糟糕的最坏情况。因此,我认为无论预期分布如何,二进制搜索仍然是最好的算法,因为它具有最好的最坏情况行为。我将根据您的描述假设:
- X是均匀分布的
是您要搜索的数据,它存储在排序表中Y=1/X
- 给定值y,需要在上表中对其进行二进制搜索
[0,1]
范围内有均匀分布的值,并且查询的是0.25
,最好不要查看范围的中心,而是查看范围的第一季度
要对1/X数据使用相同的技术,请将数据存储在表中,而不是Y,而是反向1/Y。不要搜索y,而是搜索反向值1/y 您有一个条目向量,比如
[x1,x2,…,xN]
,您知道这样一个事实,即查询的分布是以概率1/x
给出的。这意味着您的查询将使用该分布进行,即在每次咨询中,您将以更高的概率获取元素xN
这会使二进制搜索树在考虑标签的情况下保持平衡,但不会强制执行任何搜索策略。该策略的一个可能变化是放宽平衡二叉搜索树的约束——父节点左侧较小,右侧较大——并实际选择父节点作为概率较高的节点,子节点作为两个最可能的元素
请注意,不是一个二叉搜索树,因为您并不是在每一步都将搜索空间除以二,而是一个关于搜索模式分布的重新平衡树。这意味着您最糟糕的搜索情况可能会达到O(N)
。例如,有v=[10,20,30,40,50,60]
:
30
/ \
20 50
/ / \
10 40 60
可以使用函数f(x)=1/x来重新排序或重新平衡:
f([10, 20, 30, 40, 50, 60]) = [0.100, 0.050, 0.033, 0.025, 0.020, 0.016]
sort(v, f(v)) = [10, 20, 30, 40, 50, 60]
进入新的搜索树,如下所示:
10 -------------> the most probable of being taken
/ \ leaving v = [[20, 30], [40, 50, 60]]
20 30 ---------> the most probable of being taken
/ \ leaving v = [[40, 50], [60]]
40 50 -------> the most probable of being taken
/ leaving v = [[60]]
60
如果您搜索10
,您只需要一次比较,但是如果您正在搜索60
,您将执行O(N)
比较,这不符合二进制搜索的条件。正如@Steve314所指出的,离完全平衡的树越远,搜索的最差情况就越差。二叉搜索和二叉树之间有着深刻的联系-二叉树基本上是一种“预先计算”的二叉搜索,其切点由树的结构决定,而不是在搜索运行时被选择。事实证明,处理每个密钥的概率“权重”有时是用二叉树完成的
一个原因是因为它是一个相当普通的二叉搜索树,但事先就知道了,完全了解查询概率
Niklaus Wirth在他的《算法和数据结构》一书中介绍了这一点,其中有几个变体(一个用于Pascal,一个用于Modula 2,一个用于Oberon),至少有一个可从他的网站下载
然而,二叉树并不总是二叉搜索树,二叉树的一个用途是派生一个搜索树
无论哪种方法,二叉树都是从分开的叶子开始构建的,在每一步,将两个最不可能的子树合并成一个更大的子树,直到只剩下一个子树。为了在每个步骤中有效地选择两个最不可能的子树,使用了优先级队列数据结构—可能是一个
一个二叉树只要构建一次就永远不会被修改,它可以有很多用途,但是一个可以有效更新的二叉树更有用。有一些权重平衡的二叉树数据结构,但我不熟悉。当心——术语“体重”
30
/ \
20 50
/ / \
10 40 60
f([10, 20, 30, 40, 50, 60]) = [0.100, 0.050, 0.033, 0.025, 0.020, 0.016]
sort(v, f(v)) = [10, 20, 30, 40, 50, 60]
10 -------------> the most probable of being taken
/ \ leaving v = [[20, 30], [40, 50, 60]]
20 30 ---------> the most probable of being taken
/ \ leaving v = [[40, 50], [60]]
40 50 -------> the most probable of being taken
/ leaving v = [[60]]
60