Here are 4 options for binary search, plus test code. In abstract terms, they look for an ordered array X [1..N], which can contain duplicate data values ββfor a specific value T.
BinSearch_A() - find an arbitrary index P for which X [P] = T.BinSearch_B() - find the minimum index P for which X [P] = T.BinSearch_C() - find the maximum index P for which X [P] = Y.BinSearch_D() - find the range of indices P..Q for which X [P] = T (but X [P-1]! = T) and for which X [Q] = T (but X [Q +1]! = T).
BinSearch_D() is what the question needs, but understanding the other three will help you understand the end result.
The code is based on the material in Chapter 8 of Programming Pearls, 1st Edn . It shows BinSearch_A() - which he developed in the previous chapter, and then changes it to BinSearch_B() as the first step in optimizing the search for a value in an array of exactly 1000 records.
The code presented contains pseudo-code for arrays based on 1, the actual C-code for arrays based on 0, and a test harness that validates data and results widely. These are 330 lines, of which 30 are empty, about 100 are comments, 12 are headers, types and declarations, 90 are 4 implementations, and 100 is test code.
Please note: if you know that the values ββin the array are unique, then BinSearch_D() not the right algorithm to use (use BinSearch_A() ). Similarly, if it doesn't matter which element of the set of identical elements is selected, BinSearch_D() not the right algorithm to use (use BinSearch_A() ). The two options, BinSearch_B() and BinSearch_C() are specialized, but do less work than BinSearch_D() if you only need the minimum index or the maximum index that the search is for.
#include <assert.h>
Output Example:
A Data: 1 2 2 4 5 5 5 5 5 6 8 8 9 10 T 0: A -1, B -1, C -1 T 1: A 0, B 0, C 0 T 2: A 2, B 1, C 2 T 3: A -1, B -1, C -1 T 4: A 3, B 3, C 3 T 5: A 6, B 4, C 8 T 6: A 9, B 9, C 9 T 7: A -1, B -1, C -1 T 8: A 10, B 10, C 11 T 9: A 12, B 12, C 12 T 10: A 13, B 13, C 13 T 11: A -1, B -1, C -1 B Data: 10 12 12 12 14 15 15 15 15 15 15 15 16 16 16 18 18 18 19 19 19 19 T 9: A -1, B -1, C -1 T 10: A 0, B 0, C 0 T 11: A -1, B -1, C -1 T 12: A 1, B 1, C 3 T 13: A -1, B -1, C -1 T 14: A 4, B 4, C 4 T 15: A 10, B 5, C 11 T 16: A 13, B 12, C 14 T 17: A -1, B -1, C -1 T 18: A 16, B 15, C 17 T 19: A 19, B 18, C 21 T 20: A -1, B -1, C -1 C Data: 1 2 3 4 5 6 7 8 9 10 11 12 T 0: A -1, B -1, C -1 T 1: A 0, B 0, C 0 T 2: A 1, B 1, C 1 T 3: A 2, B 2, C 2 T 4: A 3, B 3, C 3 T 5: A 4, B 4, C 4 T 6: A 5, B 5, C 5 T 7: A 6, B 6, C 6 T 8: A 7, B 7, C 7 T 9: A 8, B 8, C 8 T 10: A 9, B 9, C 9 T 11: A 10, B 10, C 10 T 12: A 11, B 11, C 11 T 13: A -1, B -1, C -1 A Data: 1 2 2 4 5 5 5 5 5 6 8 8 9 10 0: (-1, -1) vs (-1, -1) 1: (0, 0) vs (0, 0) 2: (1, 2) vs (1, 2) 3: (-1, -1) vs (-1, -1) 4: (3, 3) vs (3, 3) 5: (4, 8) vs (4, 8) 6: (9, 9) vs (9, 9) 7: (-1, -1) vs (-1, -1) 8: (10, 11) vs (10, 11) 9: (12, 12) vs (12, 12) 10: (13, 13) vs (13, 13) 11: (-1, -1) vs (-1, -1) D Data: 2 3 3 3 5 5 6 8 1: (-1, -1) vs (-1, -1) 2: (0, 0) vs (0, 0) 3: (1, 3) vs (1, 3) 4: (-1, -1) vs (-1, -1) 5: (4, 5) vs (4, 5) 6: (6, 6) vs (6, 6) 7: (-1, -1) vs (-1, -1) 8: (7, 7) vs (7, 7) 9: (-1, -1) vs (-1, -1)