Skip to content
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 75 additions & 104 deletions sorting/insertion_sort.cpp
Original file line number Diff line number Diff line change
@@ -1,101 +1,90 @@
/**
*
* \file
* \brief [Insertion Sort Algorithm
* \brief [Recursive Insertion Sort Algorithm
* (Insertion Sort)](https://en.wikipedia.org/wiki/Insertion_sort)
*
* \details
* Insertion sort is a simple sorting algorithm that builds the final
* sorted array one at a time. It is much less efficient compared to
* other sorting algorithms like heap sort, merge sort or quick sort.
* 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's stable that is it does not change the relative order of
* elements with equal keys
* 5. Works on hand means it can sort the array or list as it receives.
*
* It is based on the same idea that people use to sort the playing cards in
* their hands.
* the algorithms goes in the manner that we start iterating over the array
* of elements as soon as we find a unsorted element that is a misplaced
* element we place it at a sorted position.
*
* Example execution steps:
* 1. Suppose initially we have
* \f{bmatrix}{4 &3 &2 &5 &1\f}
* 2. We start traversing from 4 till we reach 1
* when we reach at 3 we find that it is misplaced so we take 3 and place
* it at a correct position thus the array will become
* \f{bmatrix}{3 &4 &2 &5 &1\f}
* 3. In the next iteration we are at 2 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}{2 &3 &4 &5 &1\f}
* 4. We do not do anything with 5 and move on to the next iteration and
* select 1 which is misplaced and place it at correct position. Thus, we have
* \f{bmatrix}{1 &2 &3 &4 &5\f}
* sorted array one at a time. The recursive version applies the same
* logic but sorts the sub-array recursively before inserting the current
* element in its correct position.
*/

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
#include <algorithm> // for std::is_sorted and std::swap
#include <cassert> // for assert
#include <iostream> // for std::cout and std::endl
#include <vector> // for std::vector

/** \namespace sorting
* \brief Sorting algorithms
*/
namespace sorting {
/** \brief
* Insertion Sort Function
/**
* \brief Recursive Insertion Sort Function for an array
*
* @tparam T type of array
* @param [in,out] arr Array to be sorted
* @param n Size of Array
* @tparam T Type of the elements in the array
* @param[in,out] arr Pointer to the array to be sorted
* @param[in] n Size of the array
*/
template <typename T>
void insertionSort(T *arr, int n) {
for (int i = 1; i < n; i++) {
T temp = arr[i];
int j = i - 1;
while (j >= 0 && temp < arr[j]) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
void recursiveInsertionSort(T *arr, int n) {
// Base case: Array of size 1 is already sorted
if (n <= 1) {
return;
}

// Sort the first n-1 elements recursively
recursiveInsertionSort(arr, n - 1);

// Insert the nth element at its correct position in the sorted array
T last = arr[n - 1];
int j = n - 2;

// Move elements of arr[0..n-1] that are greater than last to one
// position ahead of their current position
while (j >= 0 && arr[j] > last) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = last;
}

/** Insertion Sort Function
/**
* \brief Recursive Insertion Sort Function for a vector
*
* @tparam T type of array
* @param [in,out] arr pointer to array to be sorted
* @tparam T Type of the elements in the vector
* @param[in,out] arr Pointer to the vector to be sorted
* @param[in] n Size of the vector
*/
template <typename T>
void insertionSort(std::vector<T> *arr) {
size_t n = arr->size();

for (size_t i = 1; i < n; i++) {
T temp = arr[0][i];
int32_t j = i - 1;
while (j >= 0 && temp < arr[0][j]) {
arr[0][j + 1] = arr[0][j];
j--;
}
arr[0][j + 1] = temp;
void recursiveInsertionSort(std::vector<T> *arr, size_t n) {
// Base case: If the vector has one or fewer elements, it's already sorted
if (n <= 1) {
return;
}

// Sort the first n-1 elements recursively
recursiveInsertionSort(arr, n - 1);

// Insert the nth element at its correct position in the sorted vector
T last = arr->at(n - 1);
int j = n - 2;

while (j >= 0 && arr->at(j) > last) {
arr->at(j + 1) = arr->at(j);
j--;
}
arr->at(j + 1) = last;
}

} // namespace sorting

/**
* @brief Create a random array objecthelper function to create a random array
/**
* \brief Helper function to create a random array
*
* @tparam T type of array
* @param arr array to fill (must be pre-allocated)
* @param N number of array elements
* @tparam T Type of array elements
* @param[out] arr Pointer to the array to be filled
* @param[in] N Size of the array
*/
template <typename T>
static void create_random_array(T *arr, int N) {
Expand All @@ -105,75 +94,57 @@ static void create_random_array(T *arr, int N) {
}
}

/** Test Cases to test algorithm */
/**
* \brief Test cases to validate the recursive insertion sort algorithm
*/
void tests() {
int arr1[10] = {78, 34, 35, 6, 34, 56, 3, 56, 2, 4};
std::cout << "Test 1... ";
sorting::insertionSort(arr1, 10);
sorting::recursiveInsertionSort(arr1, 10);
assert(std::is_sorted(arr1, arr1 + 10));
std::cout << "passed" << std::endl;

int arr2[5] = {5, -3, 7, -2, 1};
std::cout << "Test 2... ";
sorting::insertionSort(arr2, 5);
sorting::recursiveInsertionSort(arr2, 5);
assert(std::is_sorted(arr2, arr2 + 5));
std::cout << "passed" << std::endl;

float arr3[5] = {5.6, -3.1, -3.0, -2.1, 1.8};
std::cout << "Test 3... ";
sorting::insertionSort(arr3, 5);
sorting::recursiveInsertionSort(arr3, 5);
assert(std::is_sorted(arr3, arr3 + 5));
std::cout << "passed" << std::endl;

std::vector<float> arr4({5.6, -3.1, -3.0, -2.1, 1.8});
std::cout << "Test 4... ";
sorting::insertionSort(&arr4);
sorting::recursiveInsertionSort(&arr4, arr4.size());
assert(std::is_sorted(std::begin(arr4), std::end(arr4)));
std::cout << "passed" << std::endl;

int arr5[50];
std::cout << "Test 5... ";
create_random_array(arr5, 50);
sorting::insertionSort(arr5, 50);
sorting::recursiveInsertionSort(arr5, 50);
assert(std::is_sorted(arr5, arr5 + 50));
std::cout << "passed" << std::endl;

float arr6[50];
std::cout << "Test 6... ";
create_random_array(arr6, 50);
sorting::insertionSort(arr6, 50);
sorting::recursiveInsertionSort(arr6, 50);
assert(std::is_sorted(arr6, arr6 + 50));
std::cout << "passed" << std::endl;
}

/** Main Function */
/**
* \brief Main function
*
* Empty except for the call to `tests()`.
*
* @return 0 Always returns 0.
*/
int main() {
/// Running predefined tests to test algorithm
tests();

/// For user insteraction
size_t n;
std::cout << "Enter the length of your array (0 to exit): ";
std::cin >> n;
if (n == 0) {
return 0;
}

int *arr = new int[n];
std::cout << "Enter any " << n << " Numbers for Unsorted Array : ";

for (int i = 0; i < n; i++) {
std::cin >> arr[i];
}

sorting::insertionSort(arr, n);

std::cout << "\nSorted Array : ";
for (int i = 0; i < n; i++) {
std::cout << arr[i] << " ";
}

std::cout << std::endl;
delete[] arr;
return 0;
}