二分搜索¶ ↑
一些 Ruby 方法支持在集合中进行二分搜索
Array#bsearch
-
根据给定的块返回通过二分搜索选择的元素。
Array#bsearch_index
-
根据给定的块返回通过二分搜索选择的元素的索引。
Range#bsearch
-
根据给定的块返回通过二分搜索选择的元素。
如果未给定块,则这些方法中的每一个都返回一个枚举器。
给定一个块,这些方法中的每一个都返回 self
中的一个元素(或元素索引),该元素是通过二分搜索确定的。搜索找到 self
的一个元素,该元素满足 O(log n)
操作中给定的条件,其中 n
是元素的数量。self
应按顺序排列,但不会检查这一点。
有两种搜索模式
- 查找最小值模式
-
方法
bsearch
返回块返回true
的第一个元素;该块必须返回true
或false
。 - 查找任意模式
-
方法
bsearch
查找某些元素(如果有),块返回零。该块必须返回一个数字值。
该块不应通过有时返回 true
或 false
,有时返回数字值来混合模式,但不会检查这一点。
查找最小值模式
在查找最小值模式中,该块必须返回 true
或 false
。进一步的要求(尽管未检查)是没有索引 i
和 j
,使得
-
0 <= i < j <= self.size
. -
该块对
self[i]
返回true
,对self[j]
返回false
。
不那么正式的说法:该块使得所有 false
求值元素都位于所有 true
求值元素之前。
在查找最小值模式中,方法 bsearch
返回块返回 true
的第一个元素。
示例
a = [0, 4, 7, 10, 12] a.bsearch {|x| x >= 4 } # => 4 a.bsearch {|x| x >= 6 } # => 7 a.bsearch {|x| x >= -1 } # => 0 a.bsearch {|x| x >= 100 } # => nil r = (0...a.size) r.bsearch {|i| a[i] >= 4 } #=> 1 r.bsearch {|i| a[i] >= 6 } #=> 2 r.bsearch {|i| a[i] >= 8 } #=> 3 r.bsearch {|i| a[i] >= 100 } #=> nil r = (0.0...Float::INFINITY) r.bsearch {|x| Math.log(x) >= 0 } #=> 1.0
这些块在查找最小值模式中是有意义的
a = [0, 4, 7, 10, 12] a.map {|x| x >= 4 } # => [false, true, true, true, true] a.map {|x| x >= 6 } # => [false, false, true, true, true] a.map {|x| x >= -1 } # => [true, true, true, true, true] a.map {|x| x >= 100 } # => [false, false, false, false, false]
这没有意义
a.map {|x| x == 7 } # => [false, false, true, false, false]
查找任何模式
在查找任何模式中,该块必须返回一个数字值。另一个要求(尽管未检查)是没有索引 i
和 j
,使得
-
0 <= i < j <= self.size
. -
该块对
self[i]
返回一个负值,对self[j]
返回一个正值。 -
该块对
self[i]
返回一个负值,对self[j]
返回零。 -
该块对
self[i]
返回零,对self[j]
返回一个正值。
不那么正式的说法:该块使得
-
所有正求值元素都位于所有零求值元素之前。
-
所有正求值元素都位于所有负求值元素之前。
-
所有零求值元素都位于所有负求值元素之前。
在查找任何模式中,方法 bsearch
返回块返回零的某个元素,如果没有找到此类元素,则返回 nil
。
示例
a = [0, 4, 7, 10, 12] a.bsearch {|element| 7 <=> element } # => 7 a.bsearch {|element| -1 <=> element } # => nil a.bsearch {|element| 5 <=> element } # => nil a.bsearch {|element| 15 <=> element } # => nil a = [0, 100, 100, 100, 200] r = (0..4) r.bsearch {|i| 100 - a[i] } #=> 1, 2 or 3 r.bsearch {|i| 300 - a[i] } #=> nil r.bsearch {|i| 50 - a[i] } #=> nil
这些块在查找任何模式中是有意义的
a = [0, 4, 7, 10, 12] a.map {|element| 7 <=> element } # => [1, 1, 0, -1, -1] a.map {|element| -1 <=> element } # => [-1, -1, -1, -1, -1] a.map {|element| 5 <=> element } # => [1, 1, -1, -1, -1] a.map {|element| 15 <=> element } # => [1, 1, 1, 1, 1]
这没有意义
a.map {|element| element <=> 7 } # => [-1, -1, 0, 1, 1]