c++algorithmc++11boost-iteratorspartial-sort

Elegant code to find the 5 max top number from 3 Array


I read that blog where a C# programmer show how to use LINQ to extract the 5 top numbers from 3 different Array.

I tried to do the same with C++ and wrote the following, only 5 line of code using vector, and sort. The output is 88 89 110 888 921 as expected.

But have the question is, have you a better solution ?

#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

int main(int argc, char* argv[])
{
    int Array1 [] = { 9, 65, 87, 89, 888 };
    int Array2 [] = { 1, 13, 33, 49, 921 };
    int Array3 [] = { 22, 44, 66, 88, 110 };

    vector<int> A1(begin(Array1), end(Array1)); 
    A1.insert(end(A1), begin(Array2), end(Array2)); 
    A1.insert(end(A1), begin(Array3), end(Array3));
    sort(begin(A1), end(A1));
    vector<int> max(end(A1)-5, end(A1));

    copy(begin(max), end(max), ostream_iterator<int>(cout, " "));

    return 0;
}

Solution

  • I'd use boost::zip_iterator to eleganty append the 3 input arrays, and std::nth_element with std::greater to get the 5 largest elements in unspecified order

    #include <algorithm>
    #include <functional>
    #include <iostream>
    #include <iterator>
    #include <vector>
    #include <boost/iterator/zip_iterator.hpp>
    
    int main()
    {
        int Array1 [] = { 9, 65, 87, 89, 888 };
        int Array2 [] = { 1, 13, 33, 49, 921 };
        int Array3 [] = { 22, 44, 66, 88, 110 };
    
        std::vector<int> v;
        v.reserve((sizeof(Array1) + sizeof(Array2) + sizeof(Array3)) / sizeof(int));
    
        std::for_each(
            boost::make_zip_iterator(boost::make_tuple(std::begin(Array1), std::begin(Array2), std::begin(Array3))),
            boost::make_zip_iterator(boost::make_tuple(std::end(Array1), std::end(Array2), std::end(Array3))),
            [&v](boost::tuple<int, int, int> const& t) {
                v.push_back(t.get<0>()); v.push_back(t.get<1>()); v.push_back(t.get<2>());
            }
        );
    
        std::nth_element(begin(v), begin(v) + 5, end(v), std::greater<int>());
        std::copy(begin(v), begin(v) + 5, std::ostream_iterator<int>(std::cout, " "));
    }
    

    Live Example.

    Complexity: linear O(N1 + N2 + N3).

    If you want to have the largest elements in order, you could either use a std::partial_sort instead of std::nth_element or do a post-processing std::sort on the first 5 elements of v. The complexity of std::partial_sort for the top K elements is O(N log K), which approaches O(N log N) for a full sort. For K=5, there should be little difference between std::nth_element and std::partial_sort.