forked from Bananymous/banan-os
BAN: Rewrite heap sort
Heap sort is now more close to gnulibc++ version. This is just more simplified version.
This commit is contained in:
parent
2b927b9729
commit
951873098e
|
@ -44,7 +44,7 @@ namespace BAN::sort
|
||||||
template<typename It, typename Comp = less<typename It::value_type>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void quick_sort(It begin, It end, Comp comp = {})
|
void quick_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
if (begin == end || next(begin, 1) == end)
|
if (distance(begin, end) <= 1)
|
||||||
return;
|
return;
|
||||||
It mid = detail::partition(begin, end, comp);
|
It mid = detail::partition(begin, end, comp);
|
||||||
quick_sort(begin, mid, comp);
|
quick_sort(begin, mid, comp);
|
||||||
|
@ -54,7 +54,7 @@ namespace BAN::sort
|
||||||
template<typename It, typename Comp = less<typename It::value_type>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void insertion_sort(It begin, It end, Comp comp = {})
|
void insertion_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
if (begin == end || next(begin, 1) == end)
|
if (distance(begin, end) <= 1)
|
||||||
return;
|
return;
|
||||||
for (It it1 = next(begin, 1); it1 != end; ++it1)
|
for (It it1 = next(begin, 1); it1 != end; ++it1)
|
||||||
{
|
{
|
||||||
|
@ -66,39 +66,87 @@ namespace BAN::sort
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename It, typename Comp>
|
||||||
|
void push_heap(It begin, size_t hole_index, size_t top_index, typename It::value_type value, Comp comp)
|
||||||
|
{
|
||||||
|
size_t parent = (hole_index - 1) / 2;
|
||||||
|
while (hole_index > top_index && comp(*next(begin, parent), value))
|
||||||
|
{
|
||||||
|
*next(begin, hole_index) = move(*next(begin, parent));
|
||||||
|
hole_index = parent;
|
||||||
|
parent = (hole_index - 1) / 2;
|
||||||
|
}
|
||||||
|
*next(begin, hole_index) = move(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename It, typename Comp>
|
||||||
|
void adjust_heap(It begin, size_t hole_index, size_t len, typename It::value_type value, Comp comp)
|
||||||
|
{
|
||||||
|
const size_t top_index = hole_index;
|
||||||
|
size_t child = hole_index;
|
||||||
|
while (child < (len - 1) / 2)
|
||||||
|
{
|
||||||
|
child = 2 * (child + 1);
|
||||||
|
if (comp(*next(begin, child), *next(begin, child - 1)))
|
||||||
|
child--;
|
||||||
|
*next(begin, hole_index) = move(*next(begin, child));
|
||||||
|
hole_index = child;
|
||||||
|
}
|
||||||
|
if (len % 2 == 0 && child == (len - 2) / 2)
|
||||||
|
{
|
||||||
|
child = 2 * (child + 1);
|
||||||
|
*next(begin, hole_index) = move(*next(begin, child - 1));
|
||||||
|
hole_index = child - 1;
|
||||||
|
}
|
||||||
|
push_heap(begin, hole_index, top_index, move(value), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
|
void make_heap(It begin, It end, Comp comp = {})
|
||||||
|
{
|
||||||
|
const size_t len = distance(begin, end);
|
||||||
|
if (len <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t parent = (len - 2) / 2;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
detail::adjust_heap(begin, parent, len, move(*next(begin, parent)), comp);
|
||||||
|
|
||||||
|
if (parent == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
parent--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
|
void sort_heap(It begin, It end, Comp comp = {})
|
||||||
|
{
|
||||||
|
const size_t len = distance(begin, end);
|
||||||
|
if (len <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t last = len;
|
||||||
|
while (last > 1)
|
||||||
|
{
|
||||||
|
last--;
|
||||||
|
typename It::value_type x = move(*next(begin, last));
|
||||||
|
*next(begin, last) = move(*begin);
|
||||||
|
detail::adjust_heap(begin, 0, last, move(x), comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<typename It::value_type>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void heap_sort(It begin, It end, Comp comp = {})
|
void heap_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
if (begin == end || next(begin, 1) == end)
|
make_heap(begin, end, comp);
|
||||||
return;
|
sort_heap(begin, end, comp);
|
||||||
|
|
||||||
It start = next(begin, distance(begin, end) / 2);
|
|
||||||
|
|
||||||
while (prev(end, 1) != begin)
|
|
||||||
{
|
|
||||||
if (start != begin)
|
|
||||||
--start;
|
|
||||||
else
|
|
||||||
swap(*(--end), *begin);
|
|
||||||
|
|
||||||
It root = start;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
size_t left_child = 2 * distance(begin, root) + 1;
|
|
||||||
if (left_child >= distance(begin, end))
|
|
||||||
break;
|
|
||||||
|
|
||||||
It child = next(begin, left_child);
|
|
||||||
if (next(child, 1) != end && comp(*child, *next(child, 1)))
|
|
||||||
++child;
|
|
||||||
|
|
||||||
if (!comp(*root, *child))
|
|
||||||
break;
|
|
||||||
|
|
||||||
swap(*root, *child);
|
|
||||||
root = child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
|
@ -107,7 +155,7 @@ namespace BAN::sort
|
||||||
template<typename It, typename Comp>
|
template<typename It, typename Comp>
|
||||||
void intro_sort_impl(It begin, It end, size_t max_depth, Comp comp)
|
void intro_sort_impl(It begin, It end, size_t max_depth, Comp comp)
|
||||||
{
|
{
|
||||||
if (distance(begin, end) < 16)
|
if (distance(begin, end) <= 16)
|
||||||
return insertion_sort(begin, end, comp);
|
return insertion_sort(begin, end, comp);
|
||||||
if (max_depth == 0)
|
if (max_depth == 0)
|
||||||
return heap_sort(begin, end, comp);
|
return heap_sort(begin, end, comp);
|
||||||
|
@ -121,14 +169,16 @@ namespace BAN::sort
|
||||||
template<typename It, typename Comp = less<typename It::value_type>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void intro_sort(It begin, It end, Comp comp = {})
|
void intro_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
size_t max_depth = Math::ilog2(distance(begin, end));
|
const size_t len = distance(begin, end);
|
||||||
detail::intro_sort_impl(begin, end, max_depth, comp);
|
if (len <= 1)
|
||||||
|
return;
|
||||||
|
detail::intro_sort_impl(begin, end, 2 * Math::ilog2(len), comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<typename It::value_type>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void sort(It begin, It end, Comp comp = {})
|
void sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
return sort::intro_sort(begin, end, comp);
|
return intro_sort(begin, end, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue