-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathYaroslavskiy.h++
105 lines (99 loc) · 2.53 KB
/
Yaroslavskiy.h++
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
/*
* Code due to Vladimir Yaroslavskiy
* Retrieved from http://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf
* Converted to C++ by Armin Weiß <armin.weiss@fmi.uni-stuttgart.de>
* Converted to sort inputs larger than 2^32 by Michael Axtmann <michael.axtmann@kit.edu>
*/
#include <iterator>
namespace Yaroslavskiy {
/*
private static void swap(long[] a, long i, long j) {
long temp = a[i];
a[i] = a[j];
a[j] = temp;
}*/
template<typename iter, typename comparator>
void dualPivotQuicksort(iter left, iter right, long div, comparator comp) {
using t = typename std::iterator_traits<iter>::value_type;
long len = right - left;
if (len < 27) { // insertion sort for tiny array
for (iter i = left + 1; i <= right; i++) {
for (iter j = i; j > left && comp(*j , *(j - 1)); j--) {
std::iter_swap(j, j - 1);
}
}
return;
}
long third = len / div;
// "medians"
iter m1 = left + third;
iter m2 = right - third;
if (m1 <= left) {
m1 = left + 1;
}
if (m2 >= right) {
m2 = right - 1;
}
if (comp(*m1, *m2)) {
std::iter_swap(m1, left);
std::iter_swap(m2, right);
}
else {
std::iter_swap(m1, right);
std::iter_swap(m2, left);
}
// pivots
t pivot1 = *left;
t pivot2 = *right;
// pointers
iter less = left + 1;
iter great = right - 1;
// sorting
for (iter k = less; k <= great; k++) {
if (comp(*k, pivot1)) {
std::iter_swap(k, less++);
}
else if (comp(pivot2 , *k)) {
while (k < great && comp(pivot2, *great)) {
great--;
}
std::iter_swap(k, great--);
if (comp(*k , pivot1)) {
std::iter_swap(k, less++);
}
}
}
// swaps
long dist = great - less;
if (dist < 13) {
div++;
}
std::iter_swap(less - 1, left);
std::iter_swap(great + 1, right);
// subarrays
dualPivotQuicksort(left, less - 2, div, comp );
dualPivotQuicksort(great + 2, right, div, comp );
// equal elements
if (dist > len - 13 && pivot1 != pivot2) {
for (iter k = less; k <= great; k++) {
if (!comp(pivot1, *k )) {
std::iter_swap(k, less++);
}
else if (!comp(*k ,pivot2)) {
std::iter_swap(k, great--);
if (!comp(pivot1, *k )) {
std::iter_swap(k, less++);
}
}
}
}
// subarray
if (pivot1 < pivot2) {
dualPivotQuicksort(less, great, div,comp );
}
}
template<typename iter, typename comparator>
void sort(iter begin, iter end, comparator less) {
dualPivotQuicksort(begin, end - 1, 3, less);
}
}