首页 > 解决方案 > 用c中给定数组的元素的所有(n个选择k)组合创建一个数组?

问题描述

我正在尝试制作一个函数,它采用给定数组元素的所有可能(n 选择 k)组合,其中 n 是给定数组的长度和 ka 给定数字,并将它们放入一个新数组中。为此,我首先决定创建一个中间函数 int **indextab(int size, int r),它以给定数组的大小和 r 给定数字((n 选择 k) 的 k)作为参数,并且返回一个表,其中包含给定数组索引的所有 r 大小组合。例如,indextab(3, 2) 将返回 {{0, 1}, {0, 2}, {1, 2}}。

这是我的代码(我承认我从互联网上复制了 printCombination 并稍微修改了它以匹配我的规范):

/* arr[] ---> Input Array
data[] ---> Temporary array to
store current combination
start & end ---> Staring and
Ending indexes in arr[]
index ---> Current index in data[]
r ---> Size of a combination to be printed */
void combinationUtil(int arr[], int data[],
                    int start, int end,
                    int index, int r, int **tab, int len)
{
    // Current combination is ready
    // to be printed, print it
    if (index == r)
    {
        for (int i = 0; i < len; i++){
            if (tab[i] == NULL){
                tab[i] = data;
                break;
            }
        }
        return;
    }
 
    // replace index with all possible
    // elements. The condition "end-i+1 >= r-index"
    // makes sure that including one element
    // at index will make a combination with
    // remaining elements at remaining positions
    for (int i = start; i <= end &&
        end - i + 1 >= r - index; i++)
    {
        data[index] = arr[i];
        combinationUtil(arr, data, i+1,
                        end, index+1, r, tab, len);
    }
}

// C++ program to print all combination
// of size r in an array of size n
// The main function that prints
// all combinations of size r
// in arr[] of size n. This function
// mainly uses combinationUtil()
void printCombination(int arr[], int n, int r, int **tab, int len)
{
    // A temporary array to store
    // all combination one by one
    int data[r];
 
    // Print all combination using
    // temprary array 'data[]'
    combinationUtil(arr, data, 0, n-1, 0, r, tab, len);
}

int fact(int c, int n){
    if (n==1){
        return c;
    }
    return fact(c*n, n-1);
}

int findNumberComb(int n, int r){
    return fact(1, n)/(fact(1, r)*fact(1, n-r));
}

int **indextab(int size, int r){
    int *tab = malloc(size*sizeof(int));
    for (int i = 0; i < size; i++){
        tab[i] = i;
    }
    int len = findNumberComb(size, r);
    int **res = malloc(len*r*sizeof(int));
    printCombination(tab, size, r, res, len);
    return res;
}

这是我测试它的主要内容:

int main()
{
    int **tab = indextab(10, 3);
    for (int i = 0; i < findNumberComb(10, 3); i++){
        for (int j = 0; j < 3; j++){
            printf("%d ", tab[i][j]);
        }
    }
}

但这会产生分段错误 11。我认为这可能意味着我的 indextab 函数中的“res”选项卡太小了,但在我看来 findNumberComb(size, r) r sizeof(int) 应该是正确的 malloc 大小. 请注意,在 combineUtil 中,我使用一种非常不理想的方式来用组合填充选项卡,这是因为我不知道如何将正确的索引放入内存中。但是,我不明白为什么这不起作用。

编辑:感谢评论中的一些帮助,我将功能更改为:

int **indextab(int size, int r){
    int *tab = malloc(size*sizeof(int));
    for (int i = 0; i < size; i++){
        tab[i] = i;
    }
    int len = findNumberComb(size, r);
    int **res = calloc(len, r*sizeof(int*)*sizeof(int));
    printCombination(tab, size, r, res, len);
    return res;
}

这避免了分段错误,但我的主要打印的值太大了,有时是负数。

有人可以帮忙吗?

标签: arraysccombinations

解决方案


推荐阅读