23 template<
class Iter,
class Comp=std::ranges::less,
class Proj = std::
identity>
24 constexpr void bubble_up(Iter begin, Iter current, Comp comp = {}, Proj proj = {})
26 if(current == begin)
return;
28 auto parent{begin + (std::ranges::distance(begin, current) - 1) / 2};
29 if(comp(proj(*parent), proj(*current)))
31 std::ranges::iter_swap(parent, current);
32 bubble_up(begin, parent, comp, proj);
36 template<
class Iter,
class Comp=std::ranges::less,
class Proj = std::
identity>
37 constexpr void bubble_down(Iter begin, Iter current, Iter end, Comp comp = {}, Proj proj = {})
39 if(std::ranges::distance(begin, end) <= 1)
return;
41 if(2*(std::ranges::distance(begin, current) + 1) < std::ranges::distance(begin, end))
43 auto rightChild{begin + 2*(std::ranges::distance(begin, current) + 1)};
44 auto leftChild{rightChild - 1};
46 auto dominantChild{comp(proj(*rightChild), proj(*leftChild)) ? leftChild : rightChild};
47 if(comp(proj(*current), proj(*dominantChild)))
49 std::ranges::iter_swap(dominantChild, current);
50 bubble_down(begin, dominantChild, end, comp, proj);
53 else if(2* std::ranges::distance(begin, current) + 1 < std::ranges::distance(begin, end))
55 auto leftChild{begin + 2* std::ranges::distance(begin, current) + 1};
56 if(comp(proj(*current), proj(*leftChild))) std::ranges::iter_swap(leftChild, current);
60 template<
class Iter,
class Comp=std::ranges::less,
class Proj=std::
identity>
61 constexpr void make_heap(Iter begin, Iter end, Comp comp = {}, Proj proj = {})
63 if(std::ranges::distance(begin, end) <= 1)
return;
65 auto current{begin+1};
68 bubble_up(begin, current, comp, proj);
69 std::ranges::advance(current,1);
79 template<
class Iter,
class Comp=std::ranges::less,
class Proj = std::
identity>
80 constexpr void sort(Iter begin, Iter end, Comp comp = {}, Proj proj = {})
82 if(std::ranges::distance(begin, end) <= 1)
return;
84 sequoia::make_heap(begin, end, comp, proj);
87 std::ranges::iter_swap(begin, end-1);
88 bubble_down(begin, begin, end-1, comp, proj);
93 template<
class Iter,
class Comp,
class Proj>
94 inline constexpr bool merge_sortable{
96 typename std::iterator_traits<Iter>::value_type;
97 requires (std::is_copy_constructible_v<typename std::iterator_traits<Iter>::value_type> || is_initializable_v<typename std::iterator_traits<Iter>::value_type>);
99 && std::mergeable<Iter, Iter, typename std::vector<typename std::iterator_traits<Iter>::value_type>::iterator, Comp, Proj, Proj>
102 template<std::input_iterator Iter, std::weakly_incrementable OutIter,
class Comp = std::ranges::less,
class Proj = std::
identity>
103 requires merge_sortable<Iter, Comp, Proj>
104 constexpr void stable_sort(Iter first, Iter last, OutIter out, Comp compare = {}, Proj proj = {})
106 const auto dist{std::ranges::distance(first, last)};
109 const auto partition{std::ranges::next(first, dist / 2)};
110 stable_sort(first, partition, out, compare, proj);
111 stable_sort(partition, last, std::ranges::next(out, dist / 2), compare, proj);
112 std::ranges::merge(first, partition, partition, last, out, compare, proj, proj);
113 std::ranges::copy(out, std::ranges::next(out, dist), first);
116 template<std::input_iterator Iter,
class Comp = std::ranges::less,
class Proj = std::
identity>
117 requires merge_sortable<Iter, Comp, Proj>
118 constexpr void stable_sort(Iter first, Iter last, Comp compare = {}, Proj proj = {})
120 using T =
typename std::iterator_traits<Iter>::value_type;
123 if constexpr (is_initializable_v<T>)
return std::vector<T>(std::ranges::distance(first, last));
124 else if constexpr (std::is_copy_constructible_v<T>)
return std::vector<T>(first, last);
128 stable_sort(first, last, v.begin(), std::move(compare), std::move(proj));
131 template<
class Iter,
class Comp,
class Proj>
132 inline constexpr bool clusterable{
133 std::forward_iterator<Iter>
134 &&
requires(std::iter_reference_t<Iter> r, Comp comp, Proj proj){
135 { comp(proj(r), proj(r)) } -> std::convertible_to<bool>;
142 template<std::forward_iterator Iter,
class Comp=std::ranges::equal_to,
class Proj = std::
identity>
143 requires clusterable<Iter, Comp, Proj>
144 constexpr void cluster(Iter begin, Iter end, Comp comp = {}, Proj proj = {})
146 if(begin == end)
return;
149 while((current != end) && comp(proj(*current), proj(*begin))) std::ranges::advance(current, 1);
151 auto endOfCluster{current};
153 while(current != end)
155 if(comp(proj(*current), proj(*begin)))
157 std::ranges::iter_swap(endOfCluster, current);
158 std::ranges::advance(endOfCluster, 1);
161 std::ranges::advance(current, 1);
164 cluster(endOfCluster, end, comp, proj);
constexpr void cluster(Iter begin, Iter end, Comp comp={}, Proj proj={})
An algorithm which clusters together elements which compare equal.
Definition: Algorithms.hpp:144
constexpr void sort(Iter begin, Iter end, Comp comp={}, Proj proj={})
Definition: Algorithms.hpp:80
Concepts which are sufficiently general to appear in the sequoia namespace.