-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
merge_insertion_sort.cpp
163 lines (146 loc) · 4.35 KB
/
merge_insertion_sort.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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;
}