Search code examples
c++algorithmvectormergefunction-definition

Merge 2 sorted arrays into vector c++


Hi I'm trying to merge 2 sorted array into a vector.

The following is my code. I believe that I am using the correct algorithm however, when I print the vector out its only prints 1,2.

Can someone please take a look at my code?

#include <iostream>
#include <vector>
using namespace std;

vector<int> merge(int arr1[],int arr2[])
{
    int arr1size = sizeof(arr1) / sizeof(arr1[0]);
    int arr2size = sizeof(arr2) / sizeof(arr2[0]);
    vector<int> arr3;
    int i = 0, j = 0;
    while(i<arr1size && j<arr2size)
    {
        if(arr1[i] <= arr2[j])
        {
            arr3.push_back(arr1[i]);
            i++;
        }
        else
        {
            arr3.push_back(arr2[j]);
            j++;
        }
    }
    while(i<arr1size)
    {
        arr3.push_back(arr1[i]);
        i++;
    }
    while(j<arr2size)
    {
        arr3.push_back(arr2[j]);
        j++;
    }
    return arr3;
}
int main()
{
    int arr1[] = {1, 3, 5, 7};
    int arr2[] = {2, 4, 6, 8};
    vector<int> arr3;
    arr3 = merge(arr1,arr2);
    for(int i=0;i<arr3.size();i++)
    {
        cout << arr3[i] << endl;
    }
    return 0;
}

Solution

  • A function parameter that has an array type is adjusted by the compiler to pointer to the array element type. That is this function declaration

    vector<int> merge(int arr1[],int arr2[]);
    

    is adjusted by the compiler to the declaration

    vector<int> merge(int *arr1, int *arr2);
    

    On the other hand, arrays used as function arguments are converted implicitly to pointers to their first elements. That is this function call

    merge(arr1,arr2)
    

    is equivalent to the following function call

    merge( &arr1[0], &arr2[0] )
    

    Hence within the function these declarations

    int arr1size = sizeof(arr1) / sizeof(arr1[0]);
    int arr2size = sizeof(arr2) / sizeof(arr2[0]);
    

    are in turn equivalent to

    int arr1size = sizeof( int * ) / sizeof( int );
    int arr2size = sizeof( int * ) / sizeof( int );
    

    and depending on sizes of objects of the type int * and int the initializing expressions are evaluated either to 2 or 1. That is they do not yield the numbers of elements in the arrays used as function arguments.

    Moreover you should use the type size_t instead of the type int because the operator sizeof returns a value of the type size_t.

    Also the function parameters should have the qualifier const because the arrays are not changed within the function.

    You need explicitly to pass numbers of elements in each array.

    So the function declaration will look like

    std::vector<int> merge( const int arr1[], size_t n1, const int arr2[], size_t n2 );
    

    Pay attention that it is inefficient to use a vector without initially reserving enough space for added elements.

    In general you should use a qualified name of the function merge.

    The function can look the following as it is shown in the demonstrative program below

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    std::vector<int> merge( const int arr1[], size_t n1, const int arr2[], size_t n2 )
    {
        std::vector<int> arr3;
        arr3.reserve( n1 + n2 );
        
        size_t i = 0, j = 0;
        
        while ( i < n1 && j < n2 )
        {
            if( arr2[j] < arr1[i] )
            {
                arr3.push_back( arr2[j] );
                j++;
            }
            else
            {
                arr3.push_back( arr1[i] );
                i++;
            }
        }
        
        while ( i < n1 )
        {
            arr3.push_back( arr1[i] );
            i++;
        }
        
        while ( j < n2 )
        {
            arr3.push_back( arr2[j] );
            j++;
        }
        
        return arr3;
    }
    
    int main()
    {
        int arr1[] = {1, 3, 5, 7};
        int arr2[] = {2, 4, 6, 8};
        const size_t N1 = sizeof( arr1 ) / sizeof( *arr1 );
        const size_t N2 = sizeof( arr2 ) / sizeof( *arr2 );
        
        std::vector<int> arr3 = ::merge( arr1, N1, arr2, N2 );
        
        for ( const auto &item : arr3 )
        {
            std::cout << item << std::endl;
        }
        
        return 0;
    }
    

    The program output is

    1
    2
    3
    4
    5
    6
    7
    8
    

    There is already the standard algorithm std::merge that you could use instead of your user-defined function.

    Here is a demonstrative program.

    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <algorithm>
    
    
    int main()
    {
        int arr1[] = {1, 3, 5, 7};
        int arr2[] = {2, 4, 6, 8};
        const size_t N1 = sizeof( arr1 ) / sizeof( *arr1 );
        const size_t N2 = sizeof( arr2 ) / sizeof( *arr2 );
        
        std::vector<int> arr3;
        arr3.reserve( N1 + N2 );
        
        std::merge( arr1, arr1 + N1, arr2, arr2 + N2, std::back_inserter( arr3 ) );
        
        for ( const auto &item : arr3 )
        {
            std::cout << item << std::endl;
        }
        
        return 0;
    }
    

    The program output is the same as shown above.

    1
    2
    3
    4
    5
    6
    7
    8
    

    The standard algorithm also can be called the following way

    std::merge( std::begin( arr1 ), std::end( arr1 ), 
                std::begin( arr2 ), std::end( arr2 ), 
                std::back_inserter( arr3 ) );