澄清来自javadoc的集合二进制搜索的性能声明

时间:2012-01-24 20:23:19

标签: java algorithm list collections complexity-theory

我对来自Collections

binarySearch的效果分析感到困惑

它说:

  

如果指定的列表未实现RandomAccess接口   并且很大,这个方法会做一个基于迭代器的二进制搜索   执行O(n)链接遍历和O(log n)元素比较。

我不确定如何解释此O(n) + O(log n)

我的意思是,这不仅仅是简单地遍历链表并进行比较吗?我们仍然只获得O(n)

那么这句话对绩效意味着什么呢?如上所述,我无法理解与链表中的简单线性搜索的区别。

我在这里误解了什么?

2 个答案:

答案 0 :(得分:11)

首先,您必须明白,如果没有RandomAccess接口,binarySearch不能简单地从列表中访问随机元素,而是必须使用迭代器。这会导致O(n)费用。当集合实现RandomAccess时,每个元素访问的成本为O(1),并且就渐近复杂性而言可以忽略。

由于O(n)大于O(log n),因此它始终优先于O(log n)并支配复杂性。在这种情况下,binarySearch具有与简单线性搜索相同的复杂性。 那么优势是什么?

线性搜索执行O(n)比较,而O(log n)执行binarySearch而不进行随机访问。当O(logn)之前的常数很高时,这一点尤为重要。用简单的英语:当单个比较与推进迭代器相比具有非常高的成本时。这可能是非常常见的情况,因此限制比较的数量是有益的。利润!

答案 1 :(得分:2)

二进制搜索不适用于链接列表。该算法应该受益于带有随机访问的排序集合(如普通数组),它可以从一个元素快速跳转到另一个元素,在每次迭代时将剩余的搜索空间分成两部分(因此O(log N)时间复杂度。

对于链表,有一个修改后的版本,它遍历所有元素(在最坏的情况下需要通过2n元素),但不是比较每个元素,而是“探测”列表仅指定位置(因此与线性搜索相比,比较的数量较少)。

由于与普通指针迭代相比,比较通常稍微昂贵,因此总时间应该更低。这就是log N部分被单独强调的原因。