BAN: Optimize quick sort
We now use the middle element as the pivot and do three way partitioning to improve sorting with equivalent elements
This commit is contained in:
@@ -21,26 +21,47 @@ namespace BAN::sort
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename It, typename Comp>
|
template<typename It>
|
||||||
It partition(It begin, It end, Comp comp)
|
struct partition_pair
|
||||||
{
|
{
|
||||||
It pivot = prev(end, 1);
|
It lt;
|
||||||
|
It gt;
|
||||||
|
};
|
||||||
|
|
||||||
It it1 = begin;
|
template<typename It, typename Comp>
|
||||||
for (It it2 = begin; it2 != pivot; ++it2)
|
partition_pair<It> partition(It begin, It end, Comp comp)
|
||||||
|
{
|
||||||
|
It pivot = next(begin, distance(begin, end) / 2);
|
||||||
|
|
||||||
|
It lt = begin;
|
||||||
|
It eq = begin;
|
||||||
|
It gt = end;
|
||||||
|
|
||||||
|
while (eq != gt)
|
||||||
{
|
{
|
||||||
if (comp(*it2, *pivot))
|
if (comp(*eq, *pivot))
|
||||||
{
|
{
|
||||||
swap(*it1, *it2);
|
swap(*eq, *lt);
|
||||||
++it1;
|
if (pivot == lt)
|
||||||
|
pivot = eq;
|
||||||
|
++lt;
|
||||||
|
++eq;
|
||||||
|
}
|
||||||
|
else if (comp(*pivot, *eq))
|
||||||
|
{
|
||||||
|
--gt;
|
||||||
|
swap(*eq, *gt);
|
||||||
|
if (pivot == gt)
|
||||||
|
pivot = eq;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++eq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
swap(*it1, *pivot);
|
return { lt, gt };
|
||||||
|
|
||||||
return it1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||||
@@ -48,9 +69,9 @@ namespace BAN::sort
|
|||||||
{
|
{
|
||||||
if (distance(begin, end) <= 1)
|
if (distance(begin, end) <= 1)
|
||||||
return;
|
return;
|
||||||
It mid = detail::partition(begin, end, comp);
|
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||||
quick_sort(begin, mid, comp);
|
quick_sort(begin, lt, comp);
|
||||||
quick_sort(++mid, end, comp);
|
quick_sort(gt, end, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||||
@@ -85,9 +106,9 @@ namespace BAN::sort
|
|||||||
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);
|
||||||
It mid = detail::partition(begin, end, comp);
|
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||||
intro_sort_impl(begin, mid, max_depth - 1, comp);
|
intro_sort_impl(begin, lt, max_depth - 1, comp);
|
||||||
intro_sort_impl(++mid, end, max_depth - 1, comp);
|
intro_sort_impl(gt, end, max_depth - 1, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user