c++constantsnth-element

Is there a way to do nth_element together with copy of data?


I wish to compute the median value from an array of floats in C++:

float Median( FloatArray const * constFloatArray )
{
    FloatArray    scratch = FloatArray( *constFloatArray );
    int64_t const size    = scratch.GetWidth() * scratch.GetHeight();
    int64_t const mid     = size / 2;

    std::nth_element( scratch.begin(), scratch.begin() + mid, scratch.end() );

    return scratch[ mid ];
}

The FloatArray contains a regular C++ array of floats.

I'm using std::nth_element but wonder if there is a facility like nth_element that works with const data? Right now, I'm making a copy and then doing nth_element before throwing the copy away. If there isn't something like nth_element for const data, is there a more efficient approach that uses the copy step to compute information and thus avoid a potentially additional O(n) loop? Perhaps the performance impact would be negligible? My array size could be on the order of 2 billion.


Solution

  • I'm not sure if it will be more efficient but you can save half of the copying by using std::partial_sort_copy. We can use std::partial_sort_copy to copy only half of the data into a new array and it will sort it into that array as it does so. Then all you need to do is get the last element for an odd number of elements, or average of last two for even amount of elements. Using a vector that would look like

    int main() 
    {
        std::vector<int> v{5, 6, 4, 3, 2, 6, 7, 9, 3, 10};
        std::vector<int> r(v.size() / 2 + 1);
        std::partial_sort_copy(v.begin(), v.end(), r.begin(), r.end());
        if (r.size() % 2)
            std::cout << r.back();
        else
            std::cout << (r[r.size() - 1] + r[r.size() - 2]) / 2.0;
    }