20091002
We did a quick study of Binary Search, as an illustration of how we analyze D&C algorithms
Assume A[0 .. n-1] is a sorted array of n values
BinSearch(a,
b, k) // a and b are the lower and upper indices of
the part of the array we are searching, and k is the value we are
searching for
if (b < a) return -1
else
m = (a+b)/2
if A[m] == k return m
else
if A[m] < k return BinSearch(m+1,b, k)
else return BinSearch(a,m-1, k)
With any algorithm, there are two questions that must be answered
1. Does it always give the correct answer?
2. How long does it take?
With Divide and Conquer algorithms, correctness is usually established with Proof by Induction.
Base Case: If n (the number of elements being searched) = 1, then by examination the BinSearch algorithm works correctly.
I.H. Suppose that for all n <= n*, where n* is some value >= 1, the BinSearch algorithm always works correctly.
Now
let n = n*+1. If the algorithm finds the target value
immediately, it returns the correct value. If it doesn't find the
target value immediately, it recurses on a smaller set of values (i.e.
a set of size <= n*). By the IH, the algorithm returns the
correct value on any such set. The algorithm then returns this
value, which is the correct action.
Thus the algorithm works correctly on all sets of size n*+1, and by induction it works on all sets of any size.
The
computational complexity of Divide & Conquer algorithms is usually
established by solving a recurrence relation. For BinSearch, the
recurrence relation looks like this:
T(1) = c
i.e. the algorithm takes constant
time on a set containing just one value
T(n) = c + T(n/2) in general
Solving this by expansion yields the familiar result that for Binary Search, T(n) is O(log n)
We
moved on to a quick review of Quicksort, and we focussed on the
importance of the selection of the pivot value and the partitioning
step. If the pivot is either the smallest or the largest value in
the set, one of the two sides of the partition will be empty and the
other will contain n-1 values. If this happens every time we
choose a pivot, the algorithm will run in O(n^2) time. However
the percentage of permutations that will produce this pathological
behaviour is extremely small - in practice Quicksort virtually always
runs in O(n * log n) time.
However if that is not sufficient,
there IS a way to guarantee that we can get a good pivot value, one
which will guarantee that Quicksort will run in O(n * log n) time.
Stay turned ...