22 template<
class Iter,
class Comp=std::ranges::less,
class Proj = std::
identity>
23 constexpr void bubble_up(Iter begin, Iter current, Comp comp = {}, Proj proj = {})
25 if(current == begin)
return;
27 auto parent{begin + (std::ranges::distance(begin, current) - 1) / 2};
28 if(comp(proj(*parent), proj(*current)))
30 std::ranges::iter_swap(parent, current);
31 bubble_up(begin, parent, comp, proj);
35 template<
class Iter,
class Comp=std::ranges::less,
class Proj = std::
identity>
36 constexpr void bubble_down(Iter begin, Iter current, Iter end, Comp comp = {}, Proj proj = {})
38 if(std::ranges::distance(begin, end) <= 1)
return;
40 if(2*(std::ranges::distance(begin, current) + 1) < std::ranges::distance(begin, end))
42 auto rightChild{begin + 2*(std::ranges::distance(begin, current) + 1)};
43 auto leftChild{rightChild - 1};
45 auto dominantChild{comp(proj(*rightChild), proj(*leftChild)) ? leftChild : rightChild};
46 if(comp(proj(*current), proj(*dominantChild)))
48 std::ranges::iter_swap(dominantChild, current);
49 bubble_down(begin, dominantChild, end, comp, proj);
52 else if(2* std::ranges::distance(begin, current) + 1 < std::ranges::distance(begin, end))
54 auto leftChild{begin + 2* std::ranges::distance(begin, current) + 1};
55 if(comp(proj(*current), proj(*leftChild))) std::ranges::iter_swap(leftChild, current);
59 template<
class Iter,
class Comp=std::ranges::less,
class Proj=std::
identity>
60 constexpr void make_heap(Iter begin, Iter end, Comp comp = {}, Proj proj = {})
62 if(std::ranges::distance(begin, end) <= 1)
return;
64 auto current{begin+1};
67 bubble_up(begin, current, comp, proj);
68 std::ranges::advance(current,1);
78 template<
class Iter,
class Comp=std::ranges::less,
class Proj = std::
identity>
79 constexpr void sort(Iter begin, Iter end, Comp comp = {}, Proj proj = {})
81 if(std::ranges::distance(begin, end) <= 1)
return;
83 sequoia::make_heap(begin, end, comp, proj);
86 std::ranges::iter_swap(begin, end-1);
87 bubble_down(begin, begin, end-1, comp, proj);
92 template<
class Iter,
class Comp,
class Proj>
93 inline constexpr bool merge_sortable{
95 typename std::iterator_traits<Iter>::value_type;
96 requires (std::is_copy_constructible_v<typename std::iterator_traits<Iter>::value_type> || is_initializable_v<typename std::iterator_traits<Iter>::value_type>);
98 && std::mergeable<Iter, Iter, typename std::vector<typename std::iterator_traits<Iter>::value_type>::iterator, Comp, Proj, Proj>
101 template<std::input_iterator Iter, std::weakly_incrementable OutIter,
class Comp = std::ranges::less,
class Proj = std::
identity>
102 requires merge_sortable<Iter, Comp, Proj>
103 constexpr void stable_sort(Iter first, Iter last, OutIter out, Comp compare = {}, Proj proj = {})
105 const auto dist{std::ranges::distance(first, last)};
108 const auto partition{std::ranges::next(first, dist / 2)};
109 stable_sort(first, partition, out, compare, proj);
110 stable_sort(partition, last, std::ranges::next(out, dist / 2), compare, proj);
111 std::ranges::merge(first, partition, partition, last, out, compare, proj, proj);
112 std::ranges::copy(out, std::ranges::next(out, dist), first);
115 template<std::input_iterator Iter,
class Comp = std::ranges::less,
class Proj = std::
identity>
116 requires merge_sortable<Iter, Comp, Proj>
117 constexpr void stable_sort(Iter first, Iter last, Comp compare = {}, Proj proj = {})
119 using T =
typename std::iterator_traits<Iter>::value_type;
122 if constexpr (is_initializable_v<T>)
return std::vector<T>(std::ranges::distance(first, last));
123 else if constexpr (std::is_copy_constructible_v<T>)
return std::vector<T>(first, last);
127 stable_sort(first, last, v.begin(), std::move(compare), std::move(proj));
130 template<
class Iter,
class Comp,
class Proj>
131 inline constexpr bool clusterable{
132 std::forward_iterator<Iter>
133 &&
requires(std::iter_reference_t<Iter> r, Comp comp, Proj proj){
134 { comp(proj(r), proj(r)) } -> std::convertible_to<bool>;
141 template<std::forward_iterator Iter,
class Comp=std::ranges::equal_to,
class Proj = std::
identity>
142 requires clusterable<Iter, Comp, Proj>
143 constexpr void cluster(Iter begin, Iter end, Comp comp = {}, Proj proj = {})
145 if(begin == end)
return;
148 while((current != end) && comp(proj(*current), proj(*begin))) std::ranges::advance(current, 1);
150 auto endOfCluster{current};
152 while(current != end)
154 if(comp(proj(*current), proj(*begin)))
156 std::ranges::iter_swap(endOfCluster, current);
157 std::ranges::advance(endOfCluster, 1);
160 std::ranges::advance(current, 1);
163 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:143
constexpr void sort(Iter begin, Iter end, Comp comp={}, Proj proj={})
Definition: Algorithms.hpp:79
Concepts which are sufficiently general to appear in the sequoia namespace.