This is a kind of follow up to my previous sort implementation review with specific questions to quick sort, and Modern C++ idioms.
template<typename BidirIt,
typename Comparator = std::less<typename std::iterator_traits<BidirIt>::value_type>>
void partition(BidirIt first,
BidirIt last,
BidirIt & pivot,
Comparator cmp = Comparator())
{
// Last usually points to end, rather than the last element.
last--;
// Until both first and last point to the same element (always going to be the pivot).
while (first != last)
{
auto pivot_val = *pivot;
while (cmp(*first, pivot_val)) ++first;
while (cmp(pivot_val, *last)) --last;
if (first == pivot)
{
std::iter_swap(first, last);
pivot = last;
}
else
{
if (last == pivot)
{
std::iter_swap(first, last);
pivot = first;
}
}
}
}
std::vector<int> vec{ 1, 4, 5, 3, 2 };
template<typename BidirIt,
typename Comparator = std::less<typename std::iterator_traits<BidirIt>::value_type>>
void sort_quick(BidirIt first,
BidirIt last,
Comparator cmp = Comparator())
{
typedef std::iterator_traits<BidirIt>::difference_type dt;
dt size = std::distance(first, last);
// Arrays of 0 or 1 elements are considered sorted.
if (size > dt(1))
{
auto pivot = first + size / dt(2);
::partition(first, last, pivot);
// Recursive call on each partititon.
sort_quick(first, pivot);
sort_quick(std::next(pivot), last);
}
}
I am looking for any performance optimizations I may have missed in the algorithm itself, as well as Modern C++ constructs I may not be abiding by for this example.
In particular having to pass pivot by reference to partition and having to update the pivot reference if it gets swapped is pretty ugly, If anyone can think of a way around this I would love to know.
Also just realized this doesn't work with duplicates :|