Binary search

Binary search

Input is - ''ordered (sorted)'' array. Comparison is with middle item, if matched it then we found target, if middle is greater then we must check in the same way all items from the left side of the middle item, otherwise - on right side.

#include <stdio.h>
#include "algutils.h"

template<typename T>
int binsearch(T *arr, int len, const T& target)
{
    int mid, off = 0;
    while (1) {
        if (!len) return (-1);
        mid = len/2;
        if (arr[mid] == target) return (off + mid);
        len = mid;
        if (arr[mid] < target) {
            off += mid + 1;
            arr = &arr[mid+1];
        }
    }
}

/***********************************************************************
                                  Main
 ***********************************************************************/

int main(void)
{
#define LIST(...) {__VA_ARGS__}
#define TEST(EL, RESULT, L) do { \
    int arr[] = L; \
    int s = binsearch(arr, sizeofarray(arr), (EL)); \
    printf("Binary search of %d: %d (%s)\n", (EL), s, \
            s==(RESULT)?"true":"FALSE"); \
} while (0)

    TEST(1, 0, LIST(1,2,3,4,5,6,8,9,10,14,15,24,55));
    TEST(2, 1, LIST(1,2,3,4,5,6,8,9,10,14,15,24,55));
    TEST(14, 9, LIST(1,2,3,4,5,6,8,9,10,14,15,24,55));
    TEST(15, 10, LIST(1,2,3,4,5,6,8,9,10,14,15,24,55));
    TEST(24, 11, LIST(1,2,3,4,5,6,8,9,10,14,15,24,55));
    TEST(55, 12, LIST(1,2,3,4,5,6,8,9,10,14,15,24,55));
    TEST(240, -1, LIST(1,2,3,4,5,6,8,9,10,14,15,24,55));

    return (0);
}

Another implementation in Python. It determines the number of accesses to the data:

import random


def binsearch(lst, target):
    start = 0
    end = len(lst) - 1
    while start <= end:
        mid = (start + end) // 2
        if lst[mid] > target:
            end = mid - 1
        elif lst[mid] < target:
            start = mid + 1
        else:
            return mid


#########################
class ACCESS(list):
    def __init__(self, *a, **kw):
        super().__init__(*a, **kw)
        self._access = 0
    def __getitem__(self, i):
        print(f"{self._access}: get {i}")
        self._access += 1
        return super().__getitem__(i)


def randomdata(num):
    i = 0
    res = []
    while i< num:
        r = random.randint(0, num*10)
        res.append(r)
        i += 1
    res = sorted(res)
    return (res, random.choice(res))


NUM = 100
arr, x = randomdata(NUM)
print(f"Look for {x} in {arr}")
fnd = binsearch(ACCESS(arr), x)
print(f"Found {arr[fnd]} at {fnd}")

Typical output:

Look for 889 in [1, 41, 47, ...       
0: get 49                                                                                                                              
1: get 49                                                                                                                              
2: get 74                                                                                                                              
3: get 74                                                                                                                              
4: get 87                                                                                                                              
5: get 87                                                                                                                              
6: get 93                                                                                                                              
7: get 90                                                                                                                              
8: get 88                                                                                                                              
9: get 88                                                                                                                              
Found 889 at 88