Skip to content

Commit

Permalink
Update binary_insertion_sort.cpp
Browse files Browse the repository at this point in the history
Improved Commenting Explanation:
General Overview:

Detailed explanation of each function and its purpose.
Clearly indicates what each parameter is and how the function works.
Algorithm Details:

The purpose of binary search and how it helps improve the performance of insertion sort is explained.
Describes how each element is inserted in the correct place by shifting larger elements to the right.
Test Function:

Comments explain what each test case is doing, what type of data is being sorted, and how the program verifies if the sorting is successful.
This should help anyone reading the code to understand not only how the code works but also why each part is necessary.
  • Loading branch information
khushbooshakya committed Sep 24, 2024
1 parent 9374b00 commit c8d8632
Showing 1 changed file with 73 additions and 88 deletions.
161 changes: 73 additions & 88 deletions sorting/binary_insertion_sort.cpp
Original file line number Diff line number Diff line change
@@ -1,146 +1,131 @@
/**
* \file
* \brief [Binary Insertion Sort Algorithm
* (Insertion Sort)](https://en.wikipedia.org/wiki/Insertion_sort)
*
* \details
* If the cost of comparisons exceeds the cost of swaps, as is the case for
* example with string keys stored by reference or with human interaction (such
* as choosing one of a pair displayed side-by-side), then using binary
* insertion sort may yield better performance. Binary insertion sort employs a
* binary search to determine the correct location to insert new elements, and
* therefore performs ⌈log2 n⌉ comparisons in the worst case. When each element
* in the array is searched for and inserted this is O(n log n). The algorithm
* as a whole still has a running time of O(n2) on average because of the series
* * of swaps required for each insertion. However it has several advantages
* such as
* 1. Easy to implement
* 2. For small set of data it is quite efficient
* 3. More efficient that other Quadratic complexity algorithms like
* Selection sort or bubble sort.
* 4. It is efficient to use it when the cost of comparison is high.
* 5. It's stable that is it does not change the relative order of
* elements with equal keys.
* 6. It can sort the array or list as it receives.
*
* Example execution steps:
* 1. Suppose initially we have
* \f{bmatrix}{40 &30 &20 &50 &10\f}
* 2. We start traversing from 40 till we reach 10
* when we reach at 30 we find that it is not at it's correct place so we take
* 30 and place it at a correct position thus the array will become
* \f{bmatrix}{30 &40 &20 &50 &10\f}
* 3. In the next iteration we are at 20 we find that this is also misplaced so
* we place it at the correct sorted position thus the array in this iteration
* becomes
* \f{bmatrix}{20 &30 &40 &50 &10\f}
* 4. We do not do anything with 50 and move on to the next iteration and
* select 10 which is misplaced and place it at correct position. Thus, we have
* \f{bmatrix}{10 &20 &30 &40 &50\f}
*/

#include <algorithm> /// for algorithm functions
#include <cassert> /// for assert
#include <iostream> /// for IO operations
#include <vector> /// for working with vectors
#include <algorithm> /// for algorithm functions like std::is_sorted
#include <cassert> /// for assert to check if the sorting is correct
#include <iostream> /// for input-output operations
#include <vector> /// for using std::vector to store and sort the elements

/**
* \namespace sorting
* @brief Sorting algorithms
* @brief Contains sorting algorithms
*
* This namespace groups all the sorting-related algorithms together.
*/
namespace sorting {

/**
* \brief Binary search function to find the most suitable pace for an element.
* \tparam T The generic data type.
* \param arr The actual vector in which we are searching a suitable place for
* the element. \param val The value for which suitable place is to be found.
* \param low The lower bound of the range we are searching in.
* \param high The upper bound of the range we are searching in.
* \returns the index of most suitable position of val.
* \brief Binary search function to find the correct position for an element.
*
* This function uses binary search to determine the most suitable position for
* inserting a new element into an already sorted portion of the array.
*
* \tparam T The type of elements in the array (e.g., int, float, etc.).
* \param arr The array (vector) in which we are searching for the position to insert the element.
* \param val The value to be inserted in the sorted part of the array.
* \param low The lower bound (starting index) of the array range we are searching in.
* \param high The upper bound (ending index) of the array range we are searching in.
* \returns The index where the value `val` should be inserted.
*/
template <class T>
int64_t binary_search(std::vector<T> &arr, T val, int64_t low, int64_t high) {
// If the range contains only one element, return the appropriate position
if (high <= low) {
// If the value to insert is greater than the element at 'low', return 'low + 1', otherwise 'low'
return (val > arr[low]) ? (low + 1) : low;
}

// Calculate the middle index of the current range
int64_t mid = low + (high - low) / 2;

// If the value is less than the middle element, search in the left half
if (arr[mid] > val) {
return binary_search(arr, val, low, mid - 1);
} else if (arr[mid] < val) {
}
// If the value is greater than the middle element, search in the right half
else if (arr[mid] < val) {
return binary_search(arr, val, mid + 1, high);
} else {
}
// If the value is equal to the middle element, insert it just after 'mid'
else {
return mid + 1;
}
}

/**
* \brief Insertion sort function to sort the vector.
* \tparam T The generic data type.
* \param arr The actual vector to sort.
* \returns Void.
* \brief Binary Insertion Sort function that sorts the array using binary search for insertion.
*
* This function sorts the array by finding the appropriate position for each element using
* binary search and inserting it into the sorted part of the array. It reduces the number of
* comparisons compared to linear insertion sort, but the number of shifts (swaps) remains the same.
*
* \tparam T The type of elements in the array (e.g., int, float, etc.).
* \param arr The array (vector) to be sorted.
*/
template <typename T>
void insertionSort_binsrch(std::vector<T> &arr) {
int64_t n = arr.size();
int64_t n = arr.size(); // Get the size of the array

// Traverse the array from the second element to the last
for (int64_t i = 1; i < n; i++) {
T key = arr[i];
int64_t j = i - 1;
T key = arr[i]; // The current element to be inserted
int64_t j = i - 1; // The last index of the sorted part of the array

// Find the location to insert the current element using binary search
int64_t loc = sorting::binary_search(arr, key, 0, j);

// Shift elements that are greater than 'key' to one position ahead
while (j >= loc) {
arr[j + 1] = arr[j];
arr[j + 1] = arr[j]; // Move element to the right
j--;
}
arr[j + 1] = key;
arr[j + 1] = key; // Insert the key at the correct position
}
}
} // namespace sorting

/**
* @brief Self-test implementations
* @returns void
* @brief Function to test the Binary Insertion Sort algorithm with different test cases.
*
* This function tests the sorting algorithm using different sets of data
* and asserts that the array is sorted correctly after the sort operation.
*/
static void test() {
/* descriptions of the following test */
/* 1st test:
[5, -3, -1, -2, 7] returns [-3, -2, -1, 5, 7] */
// Test case 1: Sorting integers
std::vector<int64_t> arr1({5, -3, -1, -2, 7});
std::cout << "1st test... ";
sorting::insertionSort_binsrch(arr1);
assert(std::is_sorted(std::begin(arr1), std::end(arr1)));
std::cout << "passed" << std::endl;
sorting::insertionSort_binsrch(arr1); // Sort the array
assert(std::is_sorted(arr1.begin(), arr1.end())); // Check if the array is sorted
std::cout << "passed" << std::endl; // Output result if test passed

/* 2nd test:
[12, 26, 15, 91, 32, 54, 41] returns [12, 15, 26, 32, 41, 54, 91] */
// Test case 2: Sorting a larger set of integers
std::vector<int64_t> arr2({12, 26, 15, 91, 32, 54, 41});
std::cout << "2nd test... ";
sorting::insertionSort_binsrch(arr2);
assert(std::is_sorted(std::begin(arr2), std::end(arr2)));
sorting::insertionSort_binsrch(arr2); // Sort the array
assert(std::is_sorted(arr2.begin(), arr2.end())); // Check if the array is sorted
std::cout << "passed" << std::endl;

/* 3rd test:
[7.1, -2.5, -4.0, -2.1, 5.7] returns [-4.0, -2.5, -2.1, 5.7, 7.1] */
// Test case 3: Sorting floating-point numbers
std::vector<float> arr3({7.1, -2.5, -4.0, -2.1, 5.7});
std::cout << "3rd test... ";
sorting::insertionSort_binsrch(arr3);
assert(std::is_sorted(std::begin(arr3), std::end(arr3)));
sorting::insertionSort_binsrch(arr3); // Sort the array
assert(std::is_sorted(arr3.begin(), arr3.end())); // Check if the array is sorted
std::cout << "passed" << std::endl;

/* 4th test:
[12.8, -3.7, -20.7, -7.1, 2.2] returns [-20.7, -7.1, -3.7, 2.2, 12.8] */
// Test case 4: Sorting another set of floating-point numbers
std::vector<float> arr4({12.8, -3.7, -20.7, -7.1, 2.2});
std::cout << "4th test... ";
sorting::insertionSort_binsrch(arr4);
assert(std::is_sorted(std::begin(arr4), std::end(arr4)));
sorting::insertionSort_binsrch(arr4); // Sort the array
assert(std::is_sorted(arr4.begin(), arr4.end())); // Check if the array is sorted
std::cout << "passed" << std::endl;
}

/**
* @brief Main function
* @return 0 on exit.
* @brief Main function.
*
* This is the entry point of the program. It runs the test function to verify
* the correctness of the Binary Insertion Sort algorithm.
*
* @return 0 on successful execution.
*/
int main() {
test(); // run self-test implementations
return 0;
test(); // Run the test cases
return 0; // Exit the program
}

0 comments on commit c8d8632

Please sign in to comment.