mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-03-30 16:51:57 +08:00
* Create Merge-insertion sort.cpp
* fixed file path
* working code
* added documentation
* replace c-style array with std::array
* updating DIRECTORY.md
* clang-format and clang-tidy fixes for 8b3a6634
Co-authored-by: sinkyoungdeok <tlsrudejr123@nate.com>
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
This commit is contained in:
163
sorting/merge_insertion_sort.cpp
Normal file
163
sorting/merge_insertion_sort.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @file
|
||||
* @author [@sinkyoungdeok](https://github.com/sinkyoungdeok)
|
||||
* @author [Krishna Vedala](https://github.com/kvedala)
|
||||
* @brief Algorithm that combines insertion sort and merge sort. [Wiki
|
||||
* link](https://en.wikipedia.org/wiki/Merge-insertion_sort)
|
||||
*
|
||||
* @see Individual algorithms: insertion_sort.cpp and merge_sort.cpp
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
/** \namespace sorting
|
||||
* \brief Sorting algorithms
|
||||
*/
|
||||
namespace sorting {
|
||||
/** \namespace merge_insertion
|
||||
* \brief Combined Intersion-Merge sorting algorithm
|
||||
*/
|
||||
namespace merge_insertion {
|
||||
|
||||
/**
|
||||
* @brief Insertion merge algorithm
|
||||
* @see insertion_sort.cpp
|
||||
*
|
||||
* @tparam T array data type
|
||||
* @tparam N length of array
|
||||
* @param A pointer to array to sort
|
||||
* @param start start index of sorting window
|
||||
* @param end end index of sorting window
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
static void InsertionSort(std::array<T, N> *A, size_t start, size_t end) {
|
||||
size_t i = 0, j = 0;
|
||||
T *ptr = A->data();
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
T temp = ptr[i];
|
||||
j = i;
|
||||
while (j > start && temp < ptr[j - 1]) {
|
||||
ptr[j] = ptr[j - 1];
|
||||
j--;
|
||||
}
|
||||
// for (j = i; j > start && temp < ptr[j - 1]; --j) {
|
||||
// ptr[j] = ptr[j - 1];
|
||||
// }
|
||||
|
||||
ptr[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform merge of data in a window
|
||||
*
|
||||
* @tparam T array data type
|
||||
* @tparam N length of array
|
||||
* @param A pointer to array to sort
|
||||
* @param min start index of window
|
||||
* @param max end index of window
|
||||
* @param mid mid-point of window
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
static void merge(std::array<T, N> *array, size_t min, size_t max, size_t mid) {
|
||||
size_t firstIndex = min;
|
||||
size_t secondIndex = mid + 1;
|
||||
|
||||
auto ptr = array->data();
|
||||
std::array<T, N + 1> tempArray{0};
|
||||
|
||||
// While there are elements in the left or right runs
|
||||
for (size_t index = min; index <= max; index++) {
|
||||
// If left run head exists and is <= existing right run head.
|
||||
if (firstIndex <= mid &&
|
||||
(secondIndex > max || ptr[firstIndex] <= ptr[secondIndex])) {
|
||||
tempArray[index] = ptr[firstIndex];
|
||||
firstIndex++;
|
||||
} else {
|
||||
tempArray[index] = ptr[secondIndex];
|
||||
secondIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// transfer to the initial array
|
||||
memcpy(ptr + min, tempArray.data() + min, (max - min) * sizeof(T));
|
||||
// for (int index = min; index <= max; index++) ptr[index] =
|
||||
// tempArray[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Final combined algorithm.
|
||||
* Algorithm utilizes ::sorting::merge_insertion::InsertionSort if window length
|
||||
* is less than threshold, else performs merge sort recursively using
|
||||
* ::sorting::merge_insertion::mergeSort
|
||||
*
|
||||
* @tparam T array data type
|
||||
* @tparam N length of array
|
||||
* @param A pointer to array to sort
|
||||
* @param min start index of sort window
|
||||
* @param max end index of sort window
|
||||
* @param threshold window length threshold
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
void mergeSort(std::array<T, N> *array, size_t min, size_t max,
|
||||
size_t threshold) {
|
||||
// prerequisite
|
||||
if ((max - min) <= threshold) {
|
||||
InsertionSort(array, min, max);
|
||||
} else {
|
||||
// get the middle point
|
||||
size_t mid = (max + min) >> 1;
|
||||
|
||||
// apply merge sort to both parts of this
|
||||
mergeSort(array, min, mid, threshold);
|
||||
mergeSort(array, mid, max, threshold);
|
||||
|
||||
// and finally merge all that sorted stuff
|
||||
merge(array, min, max, mid);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace merge_insertion
|
||||
} // namespace sorting
|
||||
|
||||
/**
|
||||
* @brief Function to test code using random arrays
|
||||
* @returns none
|
||||
*/
|
||||
static void test() {
|
||||
constexpr size_t size = 30;
|
||||
std::array<int, size> array{0};
|
||||
// input
|
||||
for (int i = 0; i < size; i++) {
|
||||
array[i] = std::rand() % 100 - 50;
|
||||
std::cout << array[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
sorting::merge_insertion::InsertionSort(&array, 0, size);
|
||||
// sorting::merge_insertion::mergeSort(&array, 0, size, 10);
|
||||
|
||||
// output
|
||||
for (int i = 0; i < size; ++i) {
|
||||
std::cout << array[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
assert(std::is_sorted(std::begin(array), std::end(array)));
|
||||
std::cout << "Test passed\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @return 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
std::srand(std::time(nullptr));
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user