简体   繁体   中英

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;
}
int arr1size = sizeof(arr1) / sizeof(arr1[0]);

You are forgetting an extremely important fact. That is, an array as a function parameter is just a pointer (unlike other contexts). The following declarations are identical (and they redeclare the same function).

void f(int a[]);
void f(int a[10]);
void f(int* a);

I'm afraid, if you're sticking to plain arrays, you will have to pass their size around.

void f(int a[], int n);

Note that if you pass an array by reference, you do not lose size information, but you limit yourself to lvalues of array type (ie you can't pass dynamically allocated arrays or slices of a regular array)

template <int N>
void f(int (&a)[N]);

Alternatively, you could use std::array<T, N> or std::vector<T> , depending on requirements.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM