Algorithms Every Developer Should Know -  Binary Search
Tags: algorithms, csharp, sorting, binarysearch
Published: 2020-09-15 15:34:49

In this new series **"Algorithms Every Developer Should Know"**, I'm going to explore the implementation of algorithms everyone should know (if you need them, otherwise it's fine) using C#. For the first post, we will take a look at Binary Search, a search algorithm used to find the position of a specific value in a sorted array.

Using an iterative or recursive approach, we can implement the binary search algorithm, and we'll take a look at both of them.

## Table Of Contents
* [Binary Search Algorithm ](#bsa)
 * [Definition](#bsa-definition)
 * [Time Complexity](#bsa-tc)
 * [Auxiliary Space](#bsa-as)
 * [Step by Step pseudo-code](#bsa-step)
 * [Edge Cases](#bsa-edge)
* [Implementation of the Binary Search Algorithm using an iterative approach](#bsa-iterative)
* [Implementation of the Binary Search Algorithm using an iterative approach](#bsa-recursive)
* [Generic implementation of the binary search algorithm in C#](#bsa-generic)
* [Explore the code](#bsa-explore-fiddle)


# Binary Search Algorithm <a name="bsa"></a>

### Definition <a name="bsa-definition"></a>

Search a *sorted array* by repeatedly dividing the search interval in half. This algorithm is useful in finding the position of a specific value in a sorted array.

### Time Complexity <a name="bsa-tc"></a>

**O(logN)**  

Not going into detail but, but this tells us that for an array with N = 8, the output of logN is 3, which means we can split the array 3 times, so the number of steps (at most) to find the target value will be (3 + 1) = 4. Where 1 is the first attempt and also the best-case scenario in which the middle element of the array is our target value.

### Auxiliary Space <a name="bsa-as"></a>

**O(1)** 

The constant space of 1 tells us that the algorithm does not require temporary additional memory allocations to do its work.

### A step by step look at the algorithm <a name="bsa-step"></a>

Starting with the middle element:
* **1.** If the target value is equal to the middle element of the array, then return the index of the middle element -> **[goto 3]**.
* **2.** If not, then compare the middle element with the target value;
 * **2.1** If the target value is greater than the number in the middle index, then pick the elements to the right of the middle index, and ->  **[goto 1]**.
 * **2.2.** If the target value is less than the number in the middle index, then pick the elements to the left of the middle index, and ->  **[goto 1]**.
* **3.** Found a match, then **{return the index}**.
* **4.** Did not found a match, then **{return -1}**.

### Edge Cases <a name="bsa-edge"><a/>

There are some edge cases we must be aware:

#### 1. The element might not exist in the array

If the element does not exist in the array we must make sure that the search does not get out of bounds and consequently creating an exception because of it trying to access an invalid index.

#### 2. The target value could be in the rightmost or left most side of the array

#### 3. The target value could be the initial, middle element

#### 4. Duplicate entries could exist in the array

Using this algorithm to deal with duplicates is not appropriate, but it will return the position for the first element that it finds.

# Implementation of the Binary Search algorithm using an iterative approach <a name="bsa-iterative"></a>

{% gist https://gist.github.com/samfieldscc/051641f6130597e8740a3d90f16277fe %}

# Implementation of the Binary Search algorithm using a recursive approach <a name="bsa-recursive"></a>

I find this approach the most natural when I start to write this algorithm. It doesn't make it better or worse than the iterative version.

{% gist https://gist.github.com/samfieldscc/e6adda9b030e5e7bb30b67bdee8d614f %}

# Generic implementation of the binary search algorithm in C# <a name="bsa-generic"></a>

This algorithm is not necessarily used to only sort integers or numbers. You can use it to sort anything as long you can provide a way for the computer to know how to classify different objects. To see that in action, you can see [this fiddle](https://dotnetfiddle.net/6xmER0).

For this, you can use different strategies:

* The generic type you are using implements an [IComparable<T>](https://docs.microsoft.com/en-us/dotnet/api/system.icomparable-1?view=netcore-3.1) and/or [IEquatable<T>](https://docs.microsoft.com/en-us/dotnet/api/system.iequatable-1?view=netcore-3.1).
* Add parameter to the method that executes the algorithm and passes a [IComparison<T>](https://docs.microsoft.com/en-us/dotnet/api/system.comparison-1?view=netcore-3.1) parameter.
* Add parameter to the method that executes the algorithm and passes a [ICompararer<T>](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.icomparer-1?view=netcore-3.1) parameter.

# Explore the code <a name="bsa-explore-fiddle"></a>

I have added the code in [this fiddle](https://dotnetfiddle.net/OkinpG), so you can test the variations and play with the code at will to make it easier to understand the concepts.