Just for fun, I implemented a quicksort using std::partition()
and was getting a segfault. I found an example implementation here which was only slightly different and works. While I can see the advantage in efficiency in their implementation, I fail to see why mine is getting a segfault. The only difference is that I am not doing a second std::Partition
to avoid passing values that are the same as the pivot to later recursive calls. Can anyone spot my issue?
#include <algorithm>
#include <vector>
#include <iostream>
template <typename iter> void quick_sort(iter first, iter last)
{
if ( std::distance( first, last ) <= 1 )
{
return;
}
auto pivot = *std::next( first, std::distance( first, last ) / 2 );
#if 0 //works
iter midpoint1 = std::partition( first, last, [pivot](const auto& x)->bool{ return ( x < pivot ); } );
iter midpoint2 = std::partition( midpoint1, last, [pivot](const auto& x)->bool{ return !( pivot < x ); } );
quick_sort( first, midpoint1 );
quick_sort( midpoint2, last );
#else //segfaults
iter midpoint = std::partition( first, last, [pivot](const auto& x){ return ( x < pivot ); } );
quick_sort( first, midpoint );
quick_sort( midpoint, last );
#endif
}
int main()
{
std::vector<int> to_sort = {2,1,7,4,6,9,2,1,5,8,9,4,7,4,3,7,4,8,3,8,9};
quick_sort( std::begin( to_sort ), std::end( to_sort ) );
for ( auto n : to_sort )
{
std::cout << n << ',';
}
std::cout << '\n' << std::flush;
}
Consider a sequence where the pivot you choose is the smallest element.
Then your partitioning will result in an empty sequence (where you stop recursing), and the original one.
Repeat until stack-overflow, or, with tail-call-optimization, the system wearing out.
As an aside, in the Code you say works, you used greater >
once, though you should only use smaller <
.