Understanding Binary Insertion Sort

Binary Insertion Sort is a sorting algorithm that combines Insertion Sort with Binary Search for finding the location where an element should be inserted.

Implementation

void binaryInsertionSort(int arr[], int size)
{
	int key;
	int sortedIndex;
	int insertionIndex;
 
    for (int i = 1; i < size; i++)
    {
        key = arr[i];
        sortedIndex = i - 1;
        insertionIndex = binarySearch(arr, key, 0, sortedIndex);
 
        for (int j = sortedIndex; j >= insertionIndex; j--)
            arr[j + 1] = arr[j];
 
        arr[insertionIndex] = key;
    }
}

Where:

  • arr is the array to be sorted
  • size is the number of elements in the array
  • key is the selected element in the unsorted portion of the array
  • sortedIndex is the reverse index of the sorted portion of the array
  • insertionIndex is the position to insert the key into the sorted portion of the array

Binary Search Implementation

The different between the original binary search and the binary dearch used here is that its purpose is to find the correct position to insert the key value into the sorted array

int binarySearch(int arr[], int key, int low, int high)
{
    if (high <= low)
        return (key > arr[low] ? low + 1 : low);
 
    int mid = (low + high) / 2;
 
    if (key == arr[mid])
        return (mid + 1);
 
    if (key > arr[mid])
        return (binarySearch(arr, key, mid + 1, high));
 
    return (binarySearch(arr, key, low, mid - 1));
}

where:

  • arr is the sorted array in which to search
  • key is the value to search for
  • low is the lower bound index of the current search range
  • high is the higher bound index of the current search range

Consider the following array with 3 elements :

Step by step

Consider the following for loop that is the main part of the algorithm:

for (int i = 1; i < size; i++)
{
	key = arr[i];
	sortedIndex = i - 1;
	insertionIndex = binarySearch(arr, key, 0, sortedIndex);
 
	for (int j = sortedIndex; j >= insertionIndex; j--)
		arr[j + 1] = arr[j];
 
	arr[insertionIndex] = key;
}

First Iteration

Values:

key = 5
i = 1
sortedIndex = 0
insertionIndex = ?

Those are the initial values for the first iteration. Now, to know where to insert the key into the sorted portion of the array, we need to call binarySearch():

for (int i = 1; i < size; i++)
{
	key = arr[i];
	sortedIndex = i - 1;
	> insertionIndex = binarySearch(arr, key, 0, sortedIndex);
 
	for (int j = sortedIndex; j >= insertionIndex; j--)
		arr[j + 1] = arr[j];
 
	arr[insertionIndex] = key;
}
Inside binarySearch():

Values:

key = 5
low = 0
high = 0

As soon as we enter the function, the condition is met as , so we enter the return statement. In this section the key gets compared with the first element of the array. As , low gets returned.

if (high <= low)
	> return (key > arr[low] ? low + 1 : low);
 
int mid = (low + high) / 2;
 
if (key == arr[mid])
	return (mid + 1);
 
if (key > arr[mid])
	return (binarySearch(arr, key, mid + 1, high));
 
return (binarySearch(arr, key, low, mid - 1));
Back to binaryInsertionSort():

Now, we got to know the value for the insertionIndex:

key = 5
i = 1
sortedIndex = 0
insertionIndex = 0

Back to the execution, we find a for loop that goes through the sorted portion of the array in reverse order:

for (int i = 1; i < size; i++)
{
	key = arr[i];
	sortedIndex = i - 1;
	insertionIndex = binarySearch(arr, key, 0, sortedIndex);
 
	> for (int j = sortedIndex; j >= insertionIndex; j--)
		arr[j + 1] = arr[j];
 
	arr[insertionIndex] = key;
}

In the first iteration, j gets the value of 0 and as , we enter the loop. Then, the array’s element at index 1 gets the value of the array’s element at index 0.

In the second iteration, j gets decremented to -1, breaking out of the loop. After that, the key is inserted at the index 0 of the array:

for (int i = 1; i < size; i++)
{
	key = arr[i];
	sortedIndex = i - 1;
	insertionIndex = binarySearch(arr, key, 0, sortedIndex);
 
	for (int j = sortedIndex; j >= insertionIndex; j--)
		arr[j + 1] = arr[j];
 
	> arr[insertionIndex] = key;
}

Result:


Second Iteration

Values:

key = 3
i = 2
sortedIndex = 1
insertionIndex = ?

Now, we are going to enter binarySearch() again to retrieve the index for inserting the key:

Inside binarySearch():

Values:

key = 3
low = 0
high = 1

The condition base condition is false as so we go to the next line:

> if (high <= low)
	return (key > arr[low]) ? (low + 1) : low;
 
int mid = (low + high) / 2;
 
if (key == arr[mid])
	return (mid + 1);
 
if (key > arr[mid])
	return (binarySearch(arr, key, mid + 1, high));
 
return (binarySearch(arr, key, low, mid - 1));

The value for mid gets calculated resulting in 0:

key = 3
low = 0
high = 1
mid = 0
if (high <= low)
	return (key > arr[low]) ? (low + 1) : low;
 
> int mid = (low + high) / 2;
 
if (key == arr[mid])
	return (mid + 1);
 
if (key > arr[mid])
	return (binarySearch(arr, key, mid + 1, high));
 
return (binarySearch(arr, key, low, mid - 1));

Then, we check if the key is equal to arr[mid]. As , we skip this line:

if (high <= low)
	return (key > arr[low]) ? (low + 1) : low;
 
int mid = (low + high) / 2;
 
> if (key == arr[mid])
	return (mid + 1);
 
if (key > arr[mid])
	return (binarySearch(arr, key, mid + 1, high));
 
return (binarySearch(arr, key, low, mid - 1));

After that, we check if the key is greater than the arr[mid]. As m we go to the next line:

if (high <= low)
	return (key > arr[low]) ? (low + 1) : low;
 
int mid = (low + high) / 2;
 
if (key == arr[mid])
	return (mid + 1);
 
if (key > arr[mid])
	return (binarySearch(arr, key, mid + 1, high));
 
> return (binarySearch(arr, key, low, mid - 1));

Here, we recursively enter binarySearch() with the following values:

key = 3
low = 0
high = -1

As , we enter the base case. Inside it, the key which is 3 gets compared with arr[0] which is 5, as , the value for low, 0 gets returned.

> if (high <= low)
	return (key > arr[low]) ? (low + 1) : low;
 
int mid = (low + high) / 2;
 
if (key == arr[mid])
	return (mid + 1);
 
if (key > arr[mid])
	return (binarySearch(arr, key, mid + 1, high));
 
return (binarySearch(arr, key, low, mid - 1));
Back to binaryInsertionSort():

Now, we got to know the value for the insertionIndex:

key = 3
i = 2
sortedIndex = 1
insertionIndex = 0

Back to the execution, we find a for loop that goes through the sorted portion of the array in reverse order:

for (int i = 1; i < size; i++)
{
	key = arr[i];
	sortedIndex = i - 1;
	insertionIndex = binarySearch(arr, key, 0, sortedIndex);
 
	> for (int j = sortedIndex; j >= insertionIndex; j--)
		arr[j + 1] = arr[j];
 
	arr[insertionIndex] = key;
}

In the first iteration, j gets the value of 1 and as , we enter the loop. Then, the array’s element at index 2 gets the value of the array’s element at index 1.

j gets decremented to 0 and the condition is checked again. It checks as true as . Then, inside the loop, the array’s second element gets the value of the array’s first element.

j gets decremented to -1 and we break out of the loop as . After that, the key is inserted at the insertionIndex position in the array:

for (int i = 1; i < size; i++)
{
	key = arr[i];
	sortedIndex = i - 1;
	insertionIndex = binarySearch(arr, key, 0, sortedIndex);
 
	for (int j = sortedIndex; j >= insertionIndex; j--)
		arr[j + 1] = arr[j];
 
	> arr[insertionIndex] = key;
}

Result: