【问题标题】:Merge 2 sorted arrays into vector c++将2个排序数组合并到向量c++中
【发布时间】:2021-06-27 05:17:18
【问题描述】:

您好,我正在尝试将 2 个排序后的数组合并为一个向量。

以下是我的代码。但是,我相信我使用的是正确的算法,当我打印出矢量时,它只打印出 1,2。

有人可以看看我的代码吗?

#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]);。一个经典的错误。此时arr1[] 只是一个指针,而不是一个数组。您必须提供具有大小的函数,或使用std::vector
  • 您正在使用正确的代码来打印数组,因此如果打印的输出与预期不符,则您计算出错误的结果。无论如何,您缺少的只是一种技能,那就是使用调试器逐步执行代码。网络上有视频教程,可以为您使用的任何 IDE 演示这一点。使用调试器可以很容易地解决这个问题,而无需其他人的任何帮助。
  • @damien 嗯,看起来你是对的。我将 arr1size 和 arr2size 计算移到 main 并将其作为参数传递,它显示了正确的值。谢谢你的解释。

标签: c++ algorithm vector merge function-definition


【解决方案1】:
int arr1size = sizeof(arr1) / sizeof(arr1[0]);

你忘记了一个极其重要的事实。也就是说,数组作为函数参数只是一个指针(与其他上下文不同)。以下声明是相同的(并且它们重新声明了相同的函数)。

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

恐怕,如果你坚持使用普通数组,你将不得不传递它们的大小。

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

请注意,如果您通过引用传递数组,您确实不会丢失大小信息,但您将自己限制为数组类型的左值(即,您不能传递动态分配的数组或正则数组)

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

或者,您可以使用std::array&lt;T, N&gt;std::vector&lt;T&gt;,具体取决于要求。

【讨论】:

  • 感谢您的解释。我不确定数组是指针的事实!另一位用户也指出了这一点。再次感谢!
  • @Vincent:请注意,数组是作为函数按值参数的指针。在许多其他上下文中,数组和指针非常不同
  • 不要忘记int x[3]; std::cout &lt;&lt; sizeof(x) / sizeof(x[0]) &lt;&lt; std::endl; 实际上会输出3,所以它比最初看起来更微妙。
【解决方案2】:

编译器将具有数组类型的函数参数调整为指向数组元素类型的指针。就是这个函数声明

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

被编译器调整为声明

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

另一方面,用作函数参数的数组被隐式转换为指向其第一个元素的指针。也就是这个函数调用

merge(arr1,arr2)

相当于下面的函数调用

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

因此在函数内有这些声明

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

依次等价于

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

根据int *int 类型对象的大小,初始化表达式被评估为21。也就是说,它们不会产生用作函数参数的数组中元素的数量。

此外,您应该使用类型 size_t 而不是类型 int,因为运算符 sizeof 返回类型为 size_t 的值。

函数参数也应该有限定符const,因为数组在函数内没有改变。

您需要明确传递每个数组中的元素数量。

所以函数声明看起来像

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

请注意,在没有为添加的元素保留足够空间的情况下使用向量是低效的。

一般情况下,您应该使用函数merge 的限定名称。

函数如下面的演示程序所示

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

程序输出是

1
2
3
4
5
6
7
8

已经有标准算法std::merge,您可以使用它来代替您的用户定义函数。

这是一个演示程序。

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

程序输出同上图。

1
2
3
4
5
6
7
8

标准算法也可以这样调用

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    • 2017-02-20
    相关资源
    最近更新 更多