什么时候使用 List<T>.BinarySearch?

when to use List<T>.BinarySearch?

.NET 中的通用 List<T> 有一个 BinarySearch() 方法。 BinarySearch() 是一种搜索大型数据集的高效算法。我想我读到过,如果世界上的每个人都列在 phone 一本书中,那么二进制搜索可以在 35 步内找到任何人。在什么时候应该在 List 上使用 BinarySearch() 而不是使用带 lambda 的标准 .Where 子句?在从 Where 切换到 BinarySearch 之前,数据集应该有多大?还是 Where 已经在幕后使用了二进制搜索?

At what point should a BinarySearch() be used on a List as opposed to using the standard Where clause with a lambda?

只要列表相对于您搜索的值进行排序,无论大小如何,BinarySearch 都会(平均)为您提供比 Where 更好的性能。

如果列表是无序的,或者顺序与您要查找的值不对应(您不能使用二进制搜索在 phone 书中通过 first name) then BinarySearch 不会给你正确的结果。

请注意,它只有 returns 一个索引 ,而 Where 将为您提供 所有匹配项 条件,但如果有重复项,您可以在找到的元素的任一侧进行搜索(BinarySearch 为您提供 one 匹配的索引,不一定是 first 索引)。

显然列表越大,BinarySearch 给您的改进就越大。

does Where already use a binary search behind the scenes?

否 - 它按物理顺序遍历列表。

When to use List<T>.BinarySearch?

如您在 documentation manual 中所读:

Searches the entire sorted List<T> for an element using the default comparer and returns the zero-based index of the element.

此外,它只能用于匹配给定的 元素,而不是谓词,因为通用谓词会破坏顺序约束。

因此必须对列表进行排序,可以通过默认比较器,也可以通过给定比较器:

public int BinarySearch(T item)                        //default comparator
public int BinarySearch(T item, IComparer<T> comparer) //given comparator

算法运行 O(log n) 时间而 where 子句运行 O(n) 时间,这意味着在实践中它几乎总是优于第二个(除非该元素很可能位于列表的前面)。

Or does .Where already use a binary search behind the scenes?

不,以后不能。 A List<T> 并不总是排序的。首先检查列表是否已排序,或者对列表进行排序需要计算 O(n)O(n log n)分别与线性搜索相同甚至更昂贵。换句话说,首先检查列表是否已排序,然后 - 如果是这种情况 - 执行二进制搜索将比执行线性搜索更昂贵。线性搜索可以处理无序列表和谓词,但成本要高得多。