/* An instance of this generic class can perform binary searches on arrays (or ** segments thereof) containing values of a specified reference/class type, ** given (at time of construction) a Comparator that defines a total ordering ** on that type. Recursive and loop-based solutions are offered. ** ** Author: R. McCloskey ** Date: November 2019 */ import java.util.Comparator; public class BinarySearcher { private Comparator comp; // intended to define a total ordering on type T /* Establishes this Binary Searcher's "resident" comparator. */ public BinarySearcher(Comparator c) { this.comp = (Comparator)c; } /* Returns k satisfying 0 <= k <= ary.length such that all elements ** in ary[0..k) are less than 'key' and all elements in ary[k..ary.length) ** are greater than or equal to 'key', according to the resident comparator. ** In other words, the value returned identifies the lowest-numbered array ** location containing a value that is at least as large as the given key ** (or ary.length if there is no such location). ** ** pre: the elements in ary[) are in ascending order according to the ** resident Comparator. */ public int binSearchRec(T[] ary, T key) { return binSearchRec(ary, 0, ary.length, key); } /* Same description as method above. */ public int binSearchLoop(T[] ary, T key) { return binSearchLoop(ary, 0, ary.length, key); } /* Returns k satisfying low <= k <= high such that all elements ** in ary[low..k) are less than key and all elements in ary[k..high) ** are greater than or equal to k, according to the resident comparator. ** Uses a loop. ** ** pre: 0 <= low <= high <= ary.length && the elements in ary[low..high) ** are in ascending order according to the resident Comparator. */ public int binSearchLoop(T[] ary, int low, int high, T key) { int left = low; int right = high; // loop invariant low <= left <= right <= high && // according to the resident Comparator: // every element in ary[low..left) is < key && // every element in ary[right..high) is >= key while (left != right) { int mid = (left + right) / 2; if (comp.compare(ary[mid], key) < 0) { left = mid+1; } else { right = mid; } } return low; } /* Behavior is same as method above, but this one works using recursion. */ public int binSearchRec(T[] ary, int low, int high, T key) { if (low == high) { return low; } else { int mid = (low + high) / 2; if (comp.compare(ary[mid], key) < 0) { return binSearchRec(ary, mid+1, high, key); } else { return binSearchRec(ary, low, mid, key); } } } }