-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQuickSort.hpp
More file actions
171 lines (138 loc) · 4.67 KB
/
QuickSort.hpp
File metadata and controls
171 lines (138 loc) · 4.67 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#ifndef ALGORITHMS_QUICKSORT_HPP
#define ALGORITHMS_QUICKSORT_HPP
#include <span> // std::span
#include <array> // std::array
#include <vector> // std::vector
#include "Comparable.hpp" // includes Comparable concept used as a constraint
#include <algorithm> // std::shuffle
#include <random> // std::random_device
#include <cassert> // std::assert
using namespace std;
/**
* The {@code QuickSort} class provides a public method for sorting a
* container.
*
* @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/23quicksort/Quick.java.html.
*
* @param <T> the generic type of an item in this sorting algorithm
*/
template<typename T> requires Comparable<T>
class QuickSort {
public:
explicit QuickSort<T>(span<T> a, bool reverse = false) {
random_device rd;
mt19937 g(rd());
shuffle(a.begin(), a.end(), g);
sort(a, 0, a.size() - 1, reverse);
assert(isSorted(a, reverse));
};
private:
void sort(span<T> a, int lo, int hi, bool reverse = false);
int partition(span<T> a, int lo, int hi, bool reverse = false);
void exch(span<T> a, int i, int j);
// 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 QuickSort<T>::sort(span<T> a, int lo, int hi, bool reverse) {
if (hi <= lo) return;
int j = partition(a, lo, hi, reverse);
sort(a, lo, j - 1, reverse);
sort(a, j + 1, hi, reverse);
assert(isSorted(a, lo, hi, reverse));
}
template<typename T>
requires Comparable<T>
int QuickSort<T>::partition(span<T> a, int lo, int hi, bool reverse) {
int i = lo;
int j = hi + 1;
T v = a[lo];
if (!reverse) {
while (true) {
// find item on lo to swap
while (a[++i] < v) {
if (i == hi) break;
}
// find item on hi to swap
while (v < a[--j]) {
if (j == lo) break; // redundant since a[lo] acts as sentinel
}
// check if pointers cross
if (i >= j) break;
exch(a, i, j);
}
} else {
while (true) {
// find item on lo to swap
while (a[++i] > v) {
if (i == hi) break;
}
// find item on hi to swap
while (v > a[--j]) {
if (j == lo) break; // redundant since a[lo] acts as sentinel
}
// check if pointers cross
if (i >= j) break;
exch(a, i, j);
}
}
// put partitioning item v at a[j]
exch(a, lo, j);
// now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
return j;
}
template<typename T>
requires Comparable<T>
void QuickSort<T>::exch(span<T> a, int i, int j) {
T swap = a[i];
a[i] = a[j];
a[j] = swap;
}
template<typename T>
requires Comparable<T>
bool QuickSort<T>::isSorted(span<T> a, bool reverse) {
return isSorted(a, 0, a.size() - 1, reverse);
}
template<typename T>
requires Comparable<T>
bool QuickSort<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 QuickSort class based on constructor argument types
* and number of arguments
*/
template<typename T> requires Comparable<T>
QuickSort(span<T>) -> QuickSort<T>;
template<typename T> requires Comparable<T>
QuickSort(vector<T>) -> QuickSort<T>;
template<typename T, size_t SIZE> requires Comparable<T>
QuickSort(array<T, SIZE>) -> QuickSort<T>;
template<typename T> requires Comparable<T>
QuickSort(T a[]) -> QuickSort<T>;
template<typename T> requires Comparable<T>
QuickSort(span<T>, bool reverse) -> QuickSort<T>;
template<typename T> requires Comparable<T>
QuickSort(vector<T>, bool reverse) -> QuickSort<T>;
template<typename T, size_t SIZE> requires Comparable<T>
QuickSort(array<T, SIZE>, bool reverse) -> QuickSort<T>;
template<typename T> requires Comparable<T>
QuickSort(T a[], int length, bool reverse) -> QuickSort<T>;
#endif //ALGORITHMS_QUICKSORT_HPP