首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有效二值搜索

有效二值搜索
EN

Code Review用户
提问于 2011-10-14 18:05:34
回答 6查看 11.8K关注 0票数 5

我的实施:

代码语言:javascript
复制
Array.prototype.binarySearchFast = function(search) {

  var size = this.length,
      high = size -1,
      low = 0;

  while (high > low) {

    if (this[low] === search) return low;
    else if (this[high] === search) return high;

    target = (((search - this[low]) / (this[high] - this[low])) * (high - low)) >>> 0;

    if (this[target] === search) return target;
    else if (search > this[target]) low = target + 1, high--;
    else high = target - 1, low++;
  }

  return -1;
};

正常执行:

代码语言:javascript
复制
Array.prototype.binarySearch = function(find) {
  var low = 0, high = this.length - 1,
      i, comparison;
  while (low <= high) {
    i = Math.floor((low + high) / 2);
    if (this[i] < find) { low = i + 1; continue; };
    if (this[i] > find) { high = i - 1; continue; };
    return i;
  }
  return null;
};

不同的是,我的实现是根据起始位置和结束位置的值来猜测值的索引,而不是每次直接到中间值。

我想知道是否有人能想到比原来的实现慢一些的情况。

更新:很抱歉出现了坏的例子。现在,我已经使它们更容易理解,并在jsPerf上设置了一些测试。见这里:

http://jsperf.com/binary-search-2

用我的方法,我看到了大约75%的进步。

EN

回答 6

Code Review用户

发布于 2011-10-14 23:44:55

我的建议是,不要乱搞一些经过良好和真正检验的东西:-)

不,不完全是:如果你找到了一个比它更好的算法,那就一定要使用它。然而,在这种情况下,对于一般数据来说,这并不是一个改进。

二进制搜索和其他O(log N)类型算法的强大之处在于,在每次迭代时,您会将剩余搜索空间的一半处理掉。换句话说,如果初始搜索空间(数组大小)为1000,则第一次迭代将删除其中的500个。

在迭代过程中,对“中点”(在搜索空间中保留的内容与正在处理的内容之间的分隔符)的任何更改都有可能提高或降低性能。例如,将中点设置为25%可能会更快地减少搜索空间(如果您是对的)或更慢(如果您错了)。

现在,如果您知道数据的某些属性,您可以利用它来改进算法。事实上,正是关于列表的“额外”知识(排序的事实)允许您优化通常是顺序搜索到二进制搜索的内容。

所以这一切都取决于你的额外信息有多好。在这种情况下,仅两个端节点的值并不能真正表示中点应该在哪里。你只需看一看清单:

代码语言:javascript
复制
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 500, 1000]

看到这一切付诸行动。

如果您在该列表中寻找500,您可能会根据第一个和最后一个元素11000,决定它将位于中间位置,这显然不是这样的。

类似地,如果您正在寻找14,您可能首先在1.4%的标记(14/1000)附近检查元素,这可能是第一个元素,尽管它就在另一端。

当然,这并不是说其他额外的信息不会有帮助。如果您知道数据在范围内分布相当均匀,那么您的改进可能是值得的。

您还需要意识到,通常只有在大量的数据输入时才会很重要,所以即使结果更好,也不一定值得。对于100个元素,即使气泡排序速度也是惊人的:-)

票数 16
EN

Code Review用户

发布于 2014-02-13 13:39:17

看看这个http://en.wikipedia.org/wiki/Interpolation_搜索

特别是其中一段规定:

上述代码的每一次迭代都需要五到六次比较(额外的原因是在没有三次比较的情况下,通过二进制比较来区分<>和=的三种状态所需的重复)加上一些杂乱无章的算法,而二进制搜索算法可以用每次迭代编写一次比较,并且只使用平凡的整数算法。因此,它将搜索一个由一百万个元素组成的数组,不超过20个比较(涉及访问存储数组元素的缓慢内存);*击败上面所写的插值搜索不允许超过三次迭代。*

票数 6
EN

Code Review用户

发布于 2011-10-14 18:59:14

我想我应该对它们进行测试,但是我注意到这两个实现都没有参数,所以它们不知道要查找什么.

无论如何,当数组中没有均匀分布时,“快速”实现就会更慢。例如,在5中查找[1,2,3,4,5,6,7,10000]会产生类似于四个迭代而不是一个迭代的结果。

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/5363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档