Search code examples
c++sortingrecursionquicksortpartition

std::partition segfault issue


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;
}

Solution

  • 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 <.