Binary Search
| (require binary-search) | package: binary-search-lib |
This module provides functions for performing binary search where the search space is indexed by exact integers.
procedure
(binary-search data goal [ start end #:compare compare #:mode mode]) → (or/c exact-integer? #f) data : (or/c (-> exact-integer? any/c) vector?) goal : any/c start : exact-integer? = 0 end : (or/c exact-integer? #f) = #f compare : (or/c #f (-> any/c any/c (or/c '= '< '>))) = #f mode : symbol? = 'any/=
The input, data from start to end, must be sorted in ascending order according to compare. If compare is #f, then standard numeric order is used.
'any/= —
Returns any index in the given range such that (data index) is equal to goal according to compare. The result is not necessarily the least or greatest such index, but rather the first such index found during the binary search. 'least/=, 'greatest/= —
Returns the least or greatest index, respectively, such that (data index) is equal to goal. 'greatest/<, 'greatest/<= —
Returns the greatest index such that (data index) is strictly less than goal or less than or equal to goal, respectively. 'least/>, 'least/>= —
Returns the least index such that (data index) is strictly greater than goal or greater than or equal to goal, respectively.
> (define data (vector 1 3 4 4 4 9))
> (define (show-split v k) (printf "~s => ~s ~s ~s\n" k (vector-copy v 0 k) (vector-ref v k) (vector-copy v (add1 k)))) > (show-split data (binary-search data 4 #:mode 'any/=)) 3 => #(1 3 4) 4 #(4 9)
> (show-split data (binary-search data 4 #:mode 'least/=)) 2 => #(1 3) 4 #(4 4 9)
> (show-split data (binary-search data 4 #:mode 'greatest/=)) 4 => #(1 3 4 4) 4 #(9)
> (show-split data (binary-search data 4 #:mode 'greatest/<)) 1 => #(1) 3 #(4 4 4 9)
> (show-split data (binary-search data 4 #:mode 'greatest/<=)) 4 => #(1 3 4 4) 4 #(9)
> (show-split data (binary-search data 4 #:mode 'least/>)) 5 => #(1 3 4 4 4) 9 #()
> (show-split data (binary-search data 4 #:mode 'least/>=)) 2 => #(1 3) 4 #(4 4 9)
> (binary-search data 2 #:mode 'least/=) #f
> (show-split data (binary-search data 2 #:mode 'least/>)) 1 => #(1) 3 #(4 4 4 9)
If end is #f and data is a vector, then the end index is (vector-length data). If end is #f and data is a procedure, then the end index is found by repeatedly doubling the search range until it contains the correct result. If the doubling phase does not succeed within a certain number of steps (currently 100), an error is raised.
> (define (floor-div4 n) (floor (/ n 4))) > (binary-search floor-div4 5 #:mode 'least/=) 20
> (binary-search floor-div4 5 #:mode 'greatest/=) 23
> (binary-search floor-div4 5 #:mode 'least/>) 24
procedure
(binary-search-all data goal [ start end #:compare compare])
→
exact-integer? exact-integer? data : (or/c (-> exact-integer? any/c) vector?) goal : any/c start : exact-integer? = 0
end : exact-integer? = (and (vector? data) (vector-length data)) compare : (or/c #f (-> any/c any/c (or/c '= '< '>))) = #f
The input, data from start to end, must be sorted in ascending order according to compare. If compare is #f, then standard numeric order is used.
(<= start starteq endeq end)
For every index k such that (<= start k) and (< k starteq), (data k) is strictly less than goal according to compare.
For every index k such that (<= starteq k) and (< k endeq), (data k) is equal to goal according to compare.
For every index k such that (<= endeq k) and (< k end), (data k) is strictly greater than goal according to compare.
> (define data (vector 1 3 4 4 4 9))
> (define-syntax-rule (show-split2 v e) (let-values ([(starteq endeq) e]) (printf "~s ~s => ~s ~s ~s\n" starteq endeq (vector-copy v 0 starteq) (vector-copy v starteq endeq) (vector-copy v endeq)))) > (show-split2 data (binary-search-all data 4)) 2 5 => #(1 3) #(4 4 4) #(9)
> (show-split2 data (binary-search-all data 5)) 5 5 => #(1 3 4 4 4) #() #(9)
> (show-split2 data (binary-search-all data 10)) 6 6 => #(1 3 4 4 4 9) #() #()
> (show-split2 data (binary-search-all data 10 0 4)) 4 4 => #(1 3 4 4) #() #(4 9)
> (define (floor-div4 n) (floor (/ n 4))) > (binary-search-all floor-div4 5)
20
24