diff --git a/sorting/insertion_sort_recursive.cpp b/sorting/insertion_sort_recursive.cpp new file mode 100644 index 00000000000..256a27e1ce3 --- /dev/null +++ b/sorting/insertion_sort_recursive.cpp @@ -0,0 +1,152 @@ +/** + * @file + * @brief Insertion Sort Algorithm + * @author [Dhanush S](https://github.com/Fandroid745) + * + * @details + * Insertion sort is a simple sorting algorithm that builds the final + * sorted array one element 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: + * - Easy to implement. + * - Efficient for small data sets. + * - More efficient than other O(n²) algorithms like selection sort or bubble sort. + * - Stable: it does not change the relative order of elements with equal keys. + * + * Insertion sort works similarly to how people sort playing cards in their hands. + * The algorithm iterates through the list and inserts each element into its correct + * position in the sorted portion of the array. + * + * The time complexity of the algorithm is \f$O(n^2)\f$, and in some cases, it + * can be \f$O(n)\f$. + * + * Example execution: + * 1. Start with the array [4, 3, 2, 5, 1]. + * 2. Insert 3 in its correct position: [3, 4, 2, 5, 1]. + * 3. Insert 2: [2, 3, 4, 5, 1]. + * 4. Continue this until the array is sorted: [1, 2, 3, 4, 5]. + */ + + +#include /// for std::is_sorted +#include /// for assert function in testing +#include /// for std::cout and std::endl +#include /// for using std::vector + +/** + * @namespace sorting + * @brief Contains sorting algorithms + */ +namespace sorting { + +/** + * @brief Insertion Sort Function + * + * @tparam T Type of the array elements + * @param[in,out] arr Array to be sorted + * @param n Size of the array + */ +template +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; + } +} + +/** + * @brief Insertion Sort for a vector + * + * @tparam T Type of the vector elements + * @param [in,out] arr Pointer to the vector to be sorted + */ +template +void insertionSort(std::vector *arr) { + size_t n = arr->size(); + + for (size_t i = 1; i < n; i++) { + T temp = arr->at(i); + int32_t j = i - 1; + while (j >= 0 && temp < arr->at(j)) { + arr->at(j + 1) = arr->at(j); + j--; + } + arr->at(j + 1) = temp; + } +} + +} // namespace sorting + +/** + * @brief Helper function to create a random array + * + * @tparam T Type of the array elements + * @param arr Array to fill (must be pre-allocated) + * @param N Number of elements in the array + */ +template +static void create_random_array(T *arr, int N) { + while (N--) { + double r = (std::rand() % 10000 - 5000) / 100.f; + arr[N] = static_cast(r); + } +} + +/** + * @brief self test implementation + * @return void + */ +static void tests() { + int arr1[10] = {78, 34, 35, 6, 34, 56, 3, 56, 2, 4}; + std::cout << "Test 1... "; + sorting::insertionSort(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); + 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); + assert(std::is_sorted(arr3, arr3 + 5)); + std::cout << "passed" << std::endl; + + std::vector arr4({5.6, -3.1, -3.0, -2.1, 1.8}); + std::cout << "Test 4... "; + sorting::insertionSort(&arr4); + 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); + 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); + assert(std::is_sorted(arr6, arr6 + 50)); + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @return 0 on successful exit. + */ +int main() { + tests(); /// run self test implementations + return 0; +}