Created
February 13, 2017 19:45
-
-
Save Morwenn/9e47936aba1ce70f484bb791ab6f3b4b to your computer and use it in GitHub Desktop.
Alternative make_poplar implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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