int mid = (low + (high-low)) / 2; // wrong formula
@paganinist good answer points out the flaws in OP's search method and with a fix.
Yet to dig deeper.
Even though some compilers might be able to "un-recurse" code (Example), recursion is not needed here. A simple loop will suffice.
Array sizes can approach near maximum or exceed the range of int
in extreme cases.
For sizes in the high int
range, the following is better. @Jonathan Leffler
// int mid = (low + high)/2; // could overflow
int mid = low + (high-low)/2; // better, will not overflow when low >= 0
To accommodate all array sizes, use size_t
instead on int
. This also handles sizes including those near and above INT_MAX
.
Candidate solution that returns the address of the matching element or NULL
if not found.
#include <stdlib.h>
#include <stdio.h>
int *BinarySearch_int(const int *array, size_t count, int key) {
while (count > 0) {
size_t mid = count / 2;
if (key > array[mid]) {
array += mid + 1;
count -= mid + 1;
} else if (key < array[mid]) {
count = mid;
} else {
return (int *) &array[mid];
}
}
return NULL;
}
Test code
bool BinarySearch_int_test(const int *array, size_t count, int key, bool target){
int *p = BinarySearch_int(array, count, key);
bool success = (p != NULL) == target && (p == NULL || *p == key);
printf("f(Array:%p count:%zu, key:%2d) --> ptr:%p value:%2d success:%d\n",
(void*) array, count, key, (void*) p, p ? *p : 0, success);
return success;
}
int main(void) {
int array[] = {10, 20, 30, 40, 50, 60};
size_t n = sizeof array / sizeof array[0];
for (size_t i = 0; i < n; i++) {
BinarySearch_int_test(array, n, array[i], 1);
}
BinarySearch_int_test(array, n, 0, 0);
for (size_t i = 0; i < n; i++) {
BinarySearch_int_test(array, n, array[i] + 1, 0);
}
}
Output
f(Array:0xffffcb90 count:6, key:10) --> ptr:0xffffcb90 value:10 success:1
...
f(Array:0xffffcb90 count:6, key:60) --> ptr:0xffffcba4 value:60 success:1
f(Array:0xffffcb90 count:6, key: 0) --> ptr:0x0 value: 0 success:1
...
f(Array:0xffffcb90 count:6, key:61) --> ptr:0x0 value: 0 success:1