diff --git a/DIRECTORY.md b/DIRECTORY.md index 567460083..4370e78d8 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -236,6 +236,7 @@ * [Heap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/heap_sort.cpp) * [Insertion Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/insertion_sort.cpp) * [Library Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/library_sort.cpp) + * [Merge Insertion Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/merge_insertion_sort.cpp) * [Merge Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/merge_sort.cpp) * [Non Recursive Merge Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/non_recursive_merge_sort.cpp) * [Numeric String Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/numeric_string_sort.cpp) diff --git a/data_structures/skip_list.cpp b/data_structures/skip_list.cpp index 793994161..9cf8c430f 100644 --- a/data_structures/skip_list.cpp +++ b/data_structures/skip_list.cpp @@ -64,7 +64,7 @@ class SkipList { SkipList() { level = 0; // Header initialization - header = std::shared_ptr(new Node(-1, MAX_LEVEL)); + header = std::make_shared(-1, MAX_LEVEL); } /** @@ -75,8 +75,9 @@ class SkipList { int randomLevel() { int lvl = 0; while (static_cast(std::rand()) / RAND_MAX < PROBABILITY && - lvl < MAX_LEVEL) + lvl < MAX_LEVEL) { lvl++; + } return lvl; } @@ -93,8 +94,9 @@ class SkipList { update.fill(nullptr); for (int i = level; i >= 0; i--) { - while (x->forward[i] != nullptr && x->forward[i]->key < key) + while (x->forward[i] != nullptr && x->forward[i]->key < key) { x = x->forward[i]; + } update[i] = x; } @@ -112,7 +114,7 @@ class SkipList { } std::shared_ptr n = - std::shared_ptr(new Node(key, rlevel, value)); + std::make_shared(key, rlevel, value); for (int i = 0; i <= rlevel; i++) { n->forward[i] = update[i]->forward[i]; update[i]->forward[i] = n; @@ -135,8 +137,9 @@ class SkipList { update.fill(nullptr); for (int i = level; i >= 0; i--) { - while (x->forward[i] != nullptr && x->forward[i]->key < key) + while (x->forward[i] != nullptr && x->forward[i]->key < key) { x = x->forward[i]; + } update[i] = x; } @@ -146,8 +149,9 @@ class SkipList { if (!doesnt_exist) { for (int i = 0; i <= level; i++) { - if (update[i]->forward[i] != x) + if (update[i]->forward[i] != x) { break; + } update[i]->forward[i] = x->forward[i]; } /* Remove empty levels*/ diff --git a/sorting/merge_insertion_sort.cpp b/sorting/merge_insertion_sort.cpp new file mode 100644 index 000000000..07b2ed19d --- /dev/null +++ b/sorting/merge_insertion_sort.cpp @@ -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 +#include +#include +#include +#include +#include + +/** \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 +static void InsertionSort(std::array *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 +static void merge(std::array *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 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 +void mergeSort(std::array *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 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; +}