Functional Problem Solving (CSC 151 2015F) : EBoards

CSC151.01 2015F, Class 48: Binary Search


Overview

Preliminaries

Admin

Upcoming Work

Extra Credit Opportunities

Academic

Peer Support

Regular Peer Support

Upcoming Peer Support

Miscellaneous

Other Good Things (No Extra Credit)

Questions

The problem of searching

Computer science is ... the study of algorithms and data

Computer scientists often look for class of problems.

Two common classes:

Analyzing algorithmic efficiency

Once we've created an algorithm for solving a problem, we want to consider how many resources are required to run the algorithm. (Number of steps, amount of memory.)

Two versions of reverse on Monday's lab.

Whenever we find an algorithm, we consider its efficiency and then ask if we can do it better.

A demo: Destructive binary search

    Look in the middle.
    If the thing you are looking for is there, you are done!
    Throw away the half that's irrelevant
    Do it again.
    Eventually you are left with one item (or none)
    You are done.

Making searching more efficient using divide-and-conquer

Considering the parameters to binary search

;;; Procedure:
;;;   binary-search
;;; Parameters:
;;;   vec, a vector
;;;   get-key, a function that extracts the important part (the "key"
;;;     from an entry)
;;;   may-precede?, a binary (two-parameter) predicate that let us
;;;     decide which part to throw away
;;;     (e.g., for numbers use < and for strings use string<=?
;;;   key, the key we are looking for
;;; Purpose:
;;;   Find the element with key key in vec.
;;; Produces:
;;;   ???, a ???
(define binary-search
  (lambda (vec get-key may-precede? key)
    ; Search a portion of the vector from lower-bound to upper-bound
    (let search-portion ([lower-bound 0]
                         [upper-bound (- (vector-length vec) 1)])
      ; If the portion is empty
      (if (> lower-bound upper-bound)
          ; Indicate the value cannot be found
          -1
          ; Otherwise, identify the middle point, the element at that 
          ; point and the key of that element.
          (let* ([midpoint (quotient (+ lower-bound upper-bound) 2)]
                 [middle-element (vector-ref vec midpoint)]
                 [middle-key (get-key middle-element)]
                 [left? (may-precede? key middle-key)]
                 [right? (may-precede? middle-key key)])
            (cond
              ; If the middle key equals the value, we use the middle value.
              [(and left? right?)
               midpoint]
              ; If the middle key is too large, look in the left half
              ; of the region.
              [left?
               (search-portion lower-bound (- midpoint 1))]
              ; Otherwise, the middle key must be too small, so look 
              ; in the right half of the region.
              [else
               (search-portion (+ midpoint 1) upper-bound)]))))))