/** * @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; }