-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMergeSortBU.hpp
More file actions
151 lines (131 loc) · 4.59 KB
/
MergeSortBU.hpp
File metadata and controls
151 lines (131 loc) · 4.59 KB
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
#ifndef ALGORITHMS_MERGESORTBU_HPP
#define ALGORITHMS_MERGESORTBU_HPP
#include <span> // std::span, std::array, std::vector
#include "Comparable.hpp" // includes Comparable concept used as a constraint
#include <algorithm> // std::min
using namespace std;
/**
* The {@code MergeSortBU} class uses merge-sort (bottom-up) to sort
* a container through invoking its
* constructor with the container variable. It is non-recursive.
*
* This implementation takes Θ(n * log(n)) time
* to sort any array of length n (assuming comparisons
* take constant time). It makes between
* ~ ½ * n * lg(n) and
* ~ 1 * n * lg(n) compares.
*
* This sorting algorithm is stable.
* It uses Θ(n) extra memory (not including the input array).
*
* @author Benjamin Chan
*
* Adapted from Algorithms, 4th edition, {@authors Robert Sedgewick and Kevin Wayne}
* and their booksite https://algs4.cs.princeton.edu/
*
* The Java program from which this C++ code was adapted from is found at
* https://algs4.cs.princeton.edu/22mergesort/MergeBU.java.html.
*
* @param <T> the generic type of an item in this sorting algorithm
*/
template<typename T> requires Comparable<T>
class MergeSortBU {
public:
/**
* Rearranges the container in ascending order, using the natural order, or descending order.
*
* @param a, the container to be sorted
* @param a boolean specifying whether it should be reverse
*/
explicit MergeSortBU<T>(span<T> a, bool reverse = false) {
int n = a.size();
vector<T> aux(n);
for (int len = 1; len < n; len *= 2) {
for (int lo = 0; lo < n - len; lo += len + len) {
int mid = lo + len - 1;
int hi = min(lo + len + len - 1, n - 1);
merge(a, aux, lo, mid, hi, reverse);
}
}
assert(isSorted(a, reverse));
};
private:
// merge the two sub-arrays
void merge(span<T> a, span<T> aux, int lo, int mid, int hi, bool reverse = false);
// check if entire container is sorted -- useful for debugging
bool isSorted(span<T> a, int lo, int hi, bool reverse = false);
// check if container is sorted between two indices, lo and hi -- useful for debugging
bool isSorted(span<T> a, bool reverse = false);
};
template<typename T>
requires Comparable<T>
void MergeSortBU<T>::merge(span<T> a, span<T> aux, int lo, int mid, int hi, bool reverse) {
// copy to aux[]
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
// merge back to a[]
int i = lo, j = mid + 1;
if (!reverse) {
for (int k = lo; k <= hi; k++) {
if (i > mid)
a[k] = aux[j++];
else if (j > hi)
a[k] = aux[i++];
else if (aux[j] < aux[i])
a[k] = aux[j++];
else
a[k] = aux[i++];
}
} else {
for (int k = lo; k <= hi; k++) {
if (i > mid)
a[k] = aux[j++];
else if (j > hi)
a[k] = aux[i++];
else if (aux[j] > aux[i])
a[k] = aux[j++];
else
a[k] = aux[i++];
}
}
}
template<typename T>
requires Comparable<T>
bool MergeSortBU<T>::isSorted(span<T> a, bool reverse) {
return isSorted(a, 0, a.size() - 1, reverse);
}
template<typename T>
requires Comparable<T>
bool MergeSortBU<T>::isSorted(span<T> a, int lo, int hi, bool reverse) {
if (!reverse) {
for (int i = lo + 1; i <= hi; i++)
if (a[i] < a[i - 1]) return false;
return true;
} else {
for (int i = lo + 1; i <= hi; i++)
if (a[i] > a[i - 1]) return false;
return true;
}
}
/**
* Deduct the type, <T>, of the MergeSort class based on constructor argument types
* and number of arguments
*/
template<typename T> requires Comparable<T>
MergeSortBU(span<T>) -> MergeSortBU<T>;
template<typename T> requires Comparable<T>
MergeSortBU(vector<T>) -> MergeSortBU<T>;
template<typename T, size_t SIZE> requires Comparable<T>
MergeSortBU(array<T, SIZE>) -> MergeSortBU<T>;
template<typename T> requires Comparable<T>
MergeSortBU(T a[]) -> MergeSortBU<T>;
template<typename T> requires Comparable<T>
MergeSortBU(span<T>, bool reverse) -> MergeSortBU<T>;
template<typename T> requires Comparable<T>
MergeSortBU(vector<T>, bool reverse) -> MergeSortBU<T>;
template<typename T, size_t SIZE> requires Comparable<T>
MergeSortBU(array<T, SIZE>, bool reverse) -> MergeSortBU<T>;
template<typename T> requires Comparable<T>
MergeSortBU(T a[], bool reverse) -> MergeSortBU<T>;
#endif //ALGORITHMS_MERGESORTBU_HPP