You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Inspired by bottom-up heapsort, it consists in changing the sift operation to perform a deep-dive to find the biggest leaf of a semipoplar while performing a single operation per level, then bubble up to find where the root must be sifted to transform the semipoplar into a proper poplar. Following what happens with bottom-up heapsort, it should lead to the following differences:
Fewer comparisons are performed on average (it might even change the upper bound).
More comparisons are performed for already sorted or almost sorted collections.
It is less cache-friendly and might be slower when comparisons are cheap.
We can use moves instead of swaps to reduce the number of moves performed (might also be done with original poplar sort?).
The only real difficulty compared to bottom-up heapsort is to compute the parent of a node. In order to do that we keep track in a bitset of whether we took left or right children when finding the leaf (shouldn't need to be bigger that the iterator's difference_type), then we can backtrack using this bitset.
Here is a very rough and unpolished preliminary implementation of the modified sift function (using cpp-sort utilities):
template<typename RandomAccessIterator, typenameSize,
typename Compare, typename Projection>
autosift(RandomAccessIterator first, Size size,
Compare compare, Projection projection)
-> void
{
using utility::iter_move;
auto&& comp = utility::as_function(compare);
auto&& proj = utility::as_function(projection);
auto size_orig = size;
if (size < 2) return;
auto root = first + (size - 1);
auto child_root1 = root - 1;
auto child_root2 = first + (size / 2 - 1);
// Find the smallest leafint step = 0;
unsignedlonglong track = 0;
auto biggest = root;
while (true) {
if (comp(proj(*child_root1), proj(*child_root2))) {
biggest = child_root2;
} else {
biggest = child_root1;
track |= 1;
}
size /= 2;
if (size < 2) break;
child_root1 = biggest - 1;
child_root2 = biggest - (size - size / 2);
track <<= 1;
++step;
}
CPPSORT_ASSERT(size == 1);
// Find where to place the rootwhile (true) {
if (comp(proj(*root), proj(*biggest))) break;
if ((track & 1) == 0) {
std::advance(biggest, size + 1);
} else {
++biggest;
}
if (biggest == root) return;
track >>= 1;
--step;
size = size * 2 + 1;
}
// Move nodes as needed until they're all in the right placeauto tmp = iter_move(root);
size = size_orig;
child_root1 = root - 1;
child_root2 = first + (size / 2 - 1);
while (true) {
auto child = (((track >> step) & 1) == 1) ? child_root1 : child_root2;
*root = iter_move(child);
if (child == biggest) {
*biggest = std::move(tmp);
return;
}
root = child;
size /= 2;
child_root1 = root - 1;
child_root2 = root - (size - size / 2);
--step;
}
}
The following benchmark comparing the number of performed comparisons between top-down and bottom-up poplar sorts show a behaviour that seems to match the expected one:
The text was updated successfully, but these errors were encountered:
Inspired by bottom-up heapsort, it consists in changing the
sift
operation to perform a deep-dive to find the biggest leaf of a semipoplar while performing a single operation per level, then bubble up to find where the root must be sifted to transform the semipoplar into a proper poplar. Following what happens with bottom-up heapsort, it should lead to the following differences:The only real difficulty compared to bottom-up heapsort is to compute the parent of a node. In order to do that we keep track in a bitset of whether we took left or right children when finding the leaf (shouldn't need to be bigger that the iterator's
difference_type
), then we can backtrack using this bitset.Here is a very rough and unpolished preliminary implementation of the modified
sift
function (using cpp-sort utilities):The following benchmark comparing the number of performed comparisons between top-down and bottom-up poplar sorts show a behaviour that seems to match the expected one:
The text was updated successfully, but these errors were encountered: