-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcounting-sort-inplace.hpp
57 lines (57 loc) · 1.58 KB
/
counting-sort-inplace.hpp
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
#ifndef COUNTING_SORT_INPLACE_HPP
#define COUNTING_SORT_INPLACE_HPP
#include <vector>
template <typename size_type, typename GetKey, typename V>
void counting_sort_inplace(V &words, GetKey getkey, size_type maxkey) {
#if 0
{ // in-place counting sort
std::vector<size_type> cnt(maxkey + 1);
for (const auto &w: words) // O(n)
++cnt[getkey(w)];
// change cnt to destination position
size_type prev = 0;
for (auto &c: cnt) { // O(k)
auto cur = c;
c = prev;
prev += cur;
}
for (size_type i = 0; i < words.size(); ) {
auto &dest = cnt[getkey(words[i])];
if (dest <= i) {
if (dest < i)
// v belongs at an earlier position. Swap it into place
swap(words[i], words[dest]);
else
// v belongs at the same position. don't visit it again
++i;
// increment the pointer for this value
++dest;
} else {
// v belongs at a later position. Something later must belong here.
// Skip it and let the later item swap in when we get there
++i;
}
} // O(n)
} // time O(n + k), space = O(k)
#else
{ // in-place counting sort
std::vector<size_type> cnt(maxkey + 1);
for (const auto &w: words) // O(n)
++cnt[getkey(w)];
// change cnt to destination position
size_type sum = 0;
for (auto &c: cnt) // O(k)
sum = c += sum;
for (size_type i = 0; i < words.size(); ++i) {
for (;;) {
auto &dest = cnt[getkey(words[i])];
auto pos = dest - 1;
if (i >= pos)
break;
swap(words[i], words[dest = pos]);
}
} // in-place cycle sort, O(n)
} // time O(n + k), space = O(k)
#endif
}
#endif // COUNTING_SORT_INPLACE_HPP