给定 C++ 中的大小,如何将数组拆分为 n 个块?

How to split array into n chunks given their sizes in C++?

假设我有一个包含 10000 个整数的数组,它将被分成 3 个子数组(在本例中为“num_jobs”)。在我的代码中,我找到了每个子数组的长度,长度存储在函数“split()”的数组“parts”中。

我的代码:

// Function that prints  
// the required sequence 
int * split(int x, int n) //x=10000,n=3
{ 
  
    // If we cannot split the  
    // number into exactly 'N' parts 
    int *parts;
    parts = new int[n];
    if(x < n) 
    {
        return parts; 
    }
          
  
    // If x % n == 0 then the minimum  
    // difference is 0 and all  
    // numbers are x / n 
    else if (x % n == 0) 
    { 
        for(int i=0;i<n;i++)
        { 
        parts[i] = (x/n); 
        }
    } 
    else
    { 
  
        // upto n-(x % n) the values  
        // will be x / n  
        // after that the values  
        // will be x / n + 1 
        int zp = n - (x % n); 
        int pp = x/n; 
        for(int i=0;i<n;i++)  
        { 
  
            if(i>= zp) 
            parts[i] = (pp + 1); 
            else
            parts[i] = pp; 
        } 
    }
    // cout<<parts[0]<<parts[1]<<parts[2];
    return parts;
} 
      

main()
{
    int num_jobs;
    cout << "Enter Number of Jobs: "; // Type a number and press enter
    cin >> num_jobs; // Get user input from the keyboard  
    int sizeOfInputArray = 10000;
    int* partsArray = split(sizeOfInputArray, num_jobs);
    
    for(int index=0;index<num_jobs;index++)
    {
        cout<<partsArray[index];
        }
}

我想做的是创建 num_jobs 个数组,每个数组的长度都存在于“partsArray”中。对于10000的长度,给定3num_jobs,它returns一个包含3333、3333、3334的数组,代表每个子数组的大小。如何处理长度为 10000 的大型数组的拆分?

首先,尽可能避免使用原始数组。 std::vector 在性能和内部实现方面几乎相同,但同时提供了强大的接口并为您处理内存。

至于 C 风格的数组,您不能将单个数组拆分成多个部分。假设你有

int* arr = new int[n];

然后你不能重新解释那个数组并开始像对待 2 个单独的数组一样对待它,因为一旦你决定释放它的内存,你将释放 arr 作为一个整体,你无法改变这种行为。但是,您可以只使用数组的一部分。假设调用一个函数,它将一个数组作为参数以及开始和结束索引,比如

void doMagic(int* arr, int begin, int end) {
    for (int i = begin; i < end; ++i) {
        //do something with arr[i]
    }
}

请注意,您可以对 std::vector 执行相同的操作。如果您想从阵列中提取数据并准备包含原始阵列部分的单个较小阵列,则必须手动进行。再次对 beginend 索引使用技巧,并在循环中将值从原始数组复制到新数组。您可以使用 std::vector 实现相同的目的,因为其中一个构造函数可以使用两个 iterators 并复制一系列元素。

最后,为了避免计算子数组大小的问题,当总大小不容易被块数整除时(​​比如 10,000 除以 3),您可以改为计算我们称它们为除法点或范围。如果你的数组有 n 个元素,你想把它分成 x 个部分,你可以计算 beginend 当前块的索引如下。

int begin = (n * current) / x;
int end = ((n * (current + 1)) / x) - 1;

正如评论中所说,使用 std::vector 会更简单,但无论如何我都会给你一个 C 数组的例子:

int ** splitArray(int *inputArray, int *parts, int num_jobs) {
    int ** subarrays = new int*[3];
    int * ptr = inputArray;
    for (int i=0; i< num_jobs; i++) {
        subarrays[i] = new int[parts[i]];
        memcpy(subarrays[i], ptr, parts[i]);
        ptr += parts[i];
    }
    return subarrays;
}

int main()
{
    int sizeOfInputArray = 10000;
    int * inputArray = new int[sizeOfInputArray];
    memset(inputArray, 0xff, sizeOfInputArray * sizeof(int)); //This sets all index to -1
    int num_jobs = 3;
    int* partsArray = split(sizeOfInputArray, num_jobs);
    
    int ** subarrays = splitArray(inputArray, partsArray, num_jobs);
    std::cout << "\n" << subarrays[0][0] << " "; //==> -1
    std::cout << "\n" << subarrays[1][0] << " "; //==> -1
    std::cout << "\n" << subarrays[2][0] << " "; //==> -1
    
    //Releases allocated memory
    for(int i=0;i<num_jobs;i++) delete subarrays[i];
    delete subarrays;
    delete inputArray;
    delete partsArray;
    return 0;
}