feat: Added merge-insertion sort from #246 (#1062)

* 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:
Krishna Vedala 2020-09-03 08:51:30 -04:00 committed by GitHub
parent a9da541127
commit 08c4a3f664
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 174 additions and 6 deletions

View File

@ -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)

View File

@ -64,7 +64,7 @@ class SkipList {
SkipList() {
level = 0;
// Header initialization
header = std::shared_ptr<Node>(new Node(-1, MAX_LEVEL));
header = std::make_shared<Node>(-1, MAX_LEVEL);
}
/**
@ -75,8 +75,9 @@ class SkipList {
int randomLevel() {
int lvl = 0;
while (static_cast<float>(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<Node> n =
std::shared_ptr<Node>(new Node(key, rlevel, value));
std::make_shared<Node>(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*/

View 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;
}