2727#include < functional>
2828#include < iterator>
2929#include < ranges>
30+ #include < utility>
3031
3132namespace itertools {
3233
@@ -53,20 +54,22 @@ namespace itertools {
5354 * @param comp Comparison function callable with two dereferenced iterators.
5455 * @return Number of swaps necessary to sort the range.
5556 */
56- template <std::forward_iterator ForwardIt, class Compare = std::less<>>
57+ template <std::forward_iterator ForwardIt, typename Compare = std::less<>>
5758 std::size_t bubble_sort (ForwardIt first, ForwardIt last, Compare comp = {}) {
58- if (first == last) { return 0 ; }
5959 std::size_t n_swaps = 0 ;
60- for (ForwardIt sorted = first; first != last; last = sorted) {
61- sorted = first;
62- for (ForwardIt curr = first, prev = first; ++curr != last; ++prev) {
63- if (comp (*curr, *prev)) {
64- std::iter_swap (curr, prev);
65- sorted = curr;
60+
61+ for (auto unsorted_end = last; first != unsorted_end;) {
62+ auto last_swap = first;
63+ for (auto curr = first, next = std::next (first); next != unsorted_end; ++curr, ++next) {
64+ if (comp (*next, *curr)) {
65+ std::iter_swap (next, curr);
66+ last_swap = next;
6667 ++n_swaps;
6768 }
6869 }
70+ unsorted_end = last_swap; // Everything after last_swap is now in final position
6971 }
72+
7073 return n_swaps;
7174 }
7275
@@ -88,17 +91,22 @@ namespace itertools {
8891 * @param comp Comparison function callable with two dereferenced iterators.
8992 * @return Number of swaps necessary to sort the range.
9093 */
91- template <std::bidirectional_iterator BidirIt, class Compare = std::less<>>
94+ template <std::bidirectional_iterator BidirIt, typename Compare = std::less<>>
9295 std::size_t insertion_sort (BidirIt first, BidirIt last, Compare comp = {}) {
93- if (first == last) { return 0 ; }
94- std::size_t swaps = 0 ;
95- for (BidirIt i = std::next (first); i != last; ++i) {
96- for (BidirIt j = i; j != first && comp (*j, *std::prev (j)); --j) {
97- std::iter_swap (std::prev (j), j);
98- ++swaps;
96+ if (first == last) return 0 ;
97+
98+ std::size_t n_swaps = 0 ;
99+
100+ for (auto unsorted_begin = std::next (first); unsorted_begin != last; ++unsorted_begin) {
101+ for (auto curr = unsorted_begin; curr != first; --curr) {
102+ auto prev = std::prev (curr);
103+ if (!comp (*curr, *prev)) break ;
104+ std::iter_swap (prev, curr);
105+ ++n_swaps;
99106 }
100107 }
101- return swaps;
108+
109+ return n_swaps;
102110 }
103111
104112 /* *
@@ -112,7 +120,7 @@ namespace itertools {
112120 * @param comp Comparison function callable with two dereferenced iterators.
113121 * @return Number of swaps necessary to sort the range.
114122 */
115- template <std::ranges::forward_range Range, class Compare = std::less<>>
123+ template <std::ranges::forward_range Range, typename Compare = std::less<>>
116124 std::size_t bubble_sort (Range &&rng, Compare comp = {}) { // NOLINT (ranges need not be forwarded)
117125 return bubble_sort (std::ranges::begin (rng), std::ranges::end (rng), comp);
118126 }
@@ -128,7 +136,7 @@ namespace itertools {
128136 * @param comp Comparison function callable with two dereferenced iterators.
129137 * @return Number of swaps necessary to sort the range.
130138 */
131- template <std::ranges::bidirectional_range Range, class Compare = std::less<>>
139+ template <std::ranges::bidirectional_range Range, typename Compare = std::less<>>
132140 std::size_t insertion_sort (Range &&rng, Compare comp = {}) { // NOLINT (ranges need not be forwarded)
133141 return insertion_sort (std::ranges::begin (rng), std::ranges::end (rng), comp);
134142 }
0 commit comments