-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathbubble_sorter.cpp
130 lines (115 loc) · 3.77 KB
/
bubble_sorter.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
/*
* Copyright (c) 2015-2021 Morwenn
* SPDX-License-Identifier: MIT
*/
#include <cstddef>
#include <functional>
#include <iterator>
#include <type_traits>
#include <cpp-sort/sorter_facade.h>
#include <cpp-sort/sorter_traits.h>
#include <cpp-sort/utility/as_function.h>
#include <cpp-sort/utility/iter_move.h>
#include <cpp-sort/utility/size.h>
#include <cpp-sort/utility/static_const.h>
namespace detail
{
template<typename ForwardIterator, typename Compare>
auto bubble_sort(ForwardIterator first, std::size_t size, Compare compare)
-> void
{
if (size < 2) return;
auto&& comp = cppsort::utility::as_function(compare);
while (--size) {
auto current = first;
auto next = std::next(current);
for (std::size_t i = 0; i < size; ++i) {
if (comp(*next, *current)) {
using cppsort::utility::iter_swap;
iter_swap(current, next);
}
++next;
++current;
}
}
}
struct bubble_sorter_impl
{
// Pair of iterators overload
template<
typename ForwardIterator,
typename Compare = std::less<>,
typename = std::enable_if_t<not cppsort::is_projection_iterator_v<
Compare, ForwardIterator
>>
>
auto operator()(ForwardIterator first, ForwardIterator last, Compare compare={}) const
-> void
{
static_assert(
std::is_base_of<
iterator_category,
typename std::iterator_traits<ForwardIterator>::iterator_category
>::value,
"bubble_sorter requires at least forward iterators"
);
bubble_sort(first, std::distance(first, last),
compare);
}
// Iterable overload
template<
typename ForwardIterable,
typename Compare = std::less<>,
typename = std::enable_if_t<not cppsort::is_projection_v<
Compare, ForwardIterable
>>
>
auto operator()(ForwardIterable&& iterable, Compare compare={}) const
-> void
{
static_assert(
std::is_base_of<
iterator_category,
typename std::iterator_traits<decltype(std::begin(iterable))>::iterator_category
>::value,
"bubble_sorter requires at least forward iterators"
);
bubble_sort(std::begin(iterable), cppsort::utility::size(iterable),
compare);
}
// Sorter traits
using iterator_category = std::forward_iterator_tag;
using is_always_stable = std::true_type;
};
}
struct bubble_sorter:
cppsort::sorter_facade<detail::bubble_sorter_impl>
{};
namespace
{
constexpr auto&& bubble_sort
= cppsort::utility::static_const<bubble_sorter>::value;
}
#include <algorithm>
#include <array>
#include <cassert>
#include <numeric>
int main()
{
// Check that the bubble_sorter can sort any permutation
// of an array of 8 values
// Fill the collection in sorted order
std::array<int, 8> collection;
std::iota(collection.begin(), collection.end(), 0);
// Projection to sort in descending order
auto projection = [](int n) { return -n; };
// For each possible permutation of collection
do
{
auto to_sort = collection;
// Bubble sort the collection
bubble_sort(to_sort, projection);
// Check that it is sorted in descending order
assert(std::is_sorted(to_sort.begin(), to_sort.end(), std::greater<>{}));
} while (std::next_permutation(collection.begin(), collection.end()));
}