Skip to content

Instantly share code, notes, and snippets.

@Morwenn
Created February 13, 2017 19:45
Show Gist options
  • Save Morwenn/9e47936aba1ce70f484bb791ab6f3b4b to your computer and use it in GitHub Desktop.
Save Morwenn/9e47936aba1ce70f484bb791ab6f3b4b to your computer and use it in GitHub Desktop.
Alternative make_poplar implementation
template<typename RandomAccessIterator, typename Compare, typename Projection>
auto make_poplar(RandomAccessIterator first, RandomAccessIterator last,
Compare compare, Projection projection)
-> void
{
auto size = std::distance(first, last);
if (size < 16) {
// A sorted collection is a valid poplar heap;
// when the heap is small, using insertion sort
// should be faster
insertion_sort(std::move(first), std::move(last),
std::move(compare), std::move(projection));
return;
}
using poplar_level_t = std::make_unsigned_t<difference_type_t<RandomAccessIterator>>;
poplar_level_t poplar_level = 1;
auto it = first;
auto next = std::next(it, 15);
while (true) {
// Make a 15 element poplar
unchecked_insertion_sort(it, next, compare, projection);
// Sift elements to collapse poplars
auto poplar_size = 15;
auto begin = it;
// The loop increment follows the binary carry sequence for some reason
for (auto i = (poplar_level & -poplar_level) >> 1 ; i != 0 ; i >>= 1) {
begin -= poplar_size;
poplar_size = 2 * poplar_size + 1;
sift(begin, poplar_size, compare, projection);
++next;
}
if (next == last) return;
it = next;
std::advance(next, 15);
++poplar_level;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment