【发布时间】:2016-07-21 11:48:10
【问题描述】:
我正在尝试实现一个密度图,该图由 n x m 维的 2D 数组表示,其中每个单元格的值介于 0 和 1 之间,表示随机找到该单元格的概率。例如:
0.04 0.06 0.10
0.50 0.01 0.05
0.09 0.10 0.05
我们有 50% 的机会找到坐标 (1,0),4% 的机会找到坐标 (0,0) 等等。
为了找到这个单元格,我使用了累积和。上面的数组将被表示为:
0.04 0.69 0.90
0.54 0.70 0.95
0.63 0.80 1.00
由于我在 C++ 中工作,因此我使用的是大小为 (n * m) 的一维数组,则上面的内容由:
0.04 0.54 0.63 0.69 0.70 0.80 0.90 0.95 1.00
要在这个概率内找到一个随机单元格,我可以使用这种线性方法:
while (internal[i] < k) {
if (internal[i] >= k) break;
i++;
}
其中k是0到1之间的随机数
然而,这很慢,因为我的数组用于表示图像(因此它可能变得非常大),而且我不得不多次调用这个函数。
为了加快程序速度,我尝试在我的数组中实现二进制搜索。这个实现如下:
int DensityMap::simple_binary_search(double value, int first, int last) {
int index = -1;
int mid_point;
while (first <= last) {
mid_point = first + (last - first) / 2;
if (value >= internal[mid_point] && value < internal[mid_point + 1]) {
index = mid_point;
break;
} else if (value < internal[mid_point]) {
last = mid_point - 1;
} else {
first = mid_point + 1;
}
}
return index;
}
返回的索引是正确的(与线性搜索相同),但速度增益相当糟糕,我不明白为什么。例如,对于 10 000 x 10 000 随机填充的密度图,二分搜索需要 3.172 秒,线性搜索需要 3.288 秒。
二进制搜索的另一个问题是,有时结果可能会有所不同。考虑以下示例:
Probability array -> 0.50 0.00 0.40 0.00 0.00 0.00 0.05 0.00 0.05
Cumulative sum -> 0.50 0.50 0.90 0.90 0.90 0.90 0.95 0.95 1.00
在这种情况下,如果我的随机数是 0.90,线性搜索将在该数字第一次出现时停止(索引 2),而二进制搜索将查看中间索引,该值也是 0.90,所以它将返回(索引 4)作为结果,这不是我想要的 ..
还有其他方法可以加快搜索速度并保持我想要的结果吗? (意思是找到一个值的第一次出现)。我想一旦我找到二进制搜索的结果,我可以反向迭代,但我担心它会进一步减慢程序,这将是非常可怕的
谢谢
【问题讨论】:
-
你的算法看起来不错。您是否检查过 while 循环了多少个循环?你是只测量搜索时间,还是整个程序运行?
-
@erip std::binary_search 只返回布尔值,即测试是否存在。
-
@user2672165 哎呀。 :)
-
我只测量了每种方法的时间,但我没有检查while的通道数。感谢您的帮助