如何在 C 中创建整数数组的所有可能组合(而不是排列)?

发布于 2025-01-17 00:42:04 字数 2364 浏览 0 评论 0原文

我想生成所有可能的整数组合,例如: 对于集合 [1, 2, 3];所有组合都是:

[
  [],       [ 3 ],
  [ 2 ],    [ 3, 2 ],
  [ 1 ],    [ 3, 1 ],
  [ 2, 1 ], [ 3, 2, 1 ]
]

我知道如何在 javascript 中做到这一点,但无法找出如何在 C 中做到这一点。 javascript 版本:

const combinations = (elements) => {
    if (elements.length === 0) return [[]];
    const firstEl = elements[0];
    const rest = elements.slice(1);

    const combsWithoutFirst = combinations(rest);
    const combsWithFirst = [];

    combsWithoutFirst.forEach(combs => {
        const combWithFirst = [...combs, firstEl];
        combsWithFirst.push(combWithFirst);
    });

    return [...combsWithoutFirst, ...combsWithFirst];
}

console.log(combinations([1, 2, 3]));

那么 c 版本可能是什么?

编辑:我到目前为止的版本,但无法正常工作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    int *values;
    size_t size;
} comb;

comb *combinations;
size_t depth;
int count;

void init()
{
    count = 1; // number of combintations so far
    int size = depth;
    for (int i = 0; i < depth; i++)
    {
        size *= 2;
    }
    combinations = malloc(sizeof(comb) * size);
}

comb *ctor(int *values, size_t size)
{
    comb *newone = malloc(sizeof(comb));
    newone->values = values;
    newone->size = size;
    return newone;
}

comb *pop_front(comb x)
{
    int newSize = x.size - 1;
    int *newVals = malloc(sizeof(int) * newSize);
    memcpy(newVals, x.values + sizeof(int), newSize);
    return ctor(newVals, newSize);
}

comb *push_back(comb x, int newValue)
{
    int newSize = x.size + 1;
    int *newVals = malloc(sizeof(int) * newSize);
    memcpy(newVals, x.values, x.size * sizeof(int));
    newVals[newSize - 1] = newValue;
    return ctor(newVals, newSize);
}

void addComb(comb *x, comb y)
{
}

comb *func(comb *elements)
{
    if (!depth)
    {
        return ctor(NULL, 0);
    }
    int firstEl = elements->values[0];
    comb *rest = pop_front(*elements);

    depth--;
    comb *combsWithoutFirst = func(rest);
    comb *combsWithFirst = ctor(NULL, 0);

    for (int i = 0; i < count; i++)
    {
        comb *combWithFirst = push_back(combsWithoutFirst[i], firstEl);
        // now add that combWithFirst to the combsWithFirst
    }

    // merge the two arrays
}

int main()
{
}

I would like to generate all posible combinations of ints, an example:
for set [1, 2, 3]; there all combinations are:

[
  [],       [ 3 ],
  [ 2 ],    [ 3, 2 ],
  [ 1 ],    [ 3, 1 ],
  [ 2, 1 ], [ 3, 2, 1 ]
]

I know, how to do that in javascript, but cannot find out, how to do the same in C. The javascript version:

const combinations = (elements) => {
    if (elements.length === 0) return [[]];
    const firstEl = elements[0];
    const rest = elements.slice(1);

    const combsWithoutFirst = combinations(rest);
    const combsWithFirst = [];

    combsWithoutFirst.forEach(combs => {
        const combWithFirst = [...combs, firstEl];
        combsWithFirst.push(combWithFirst);
    });

    return [...combsWithoutFirst, ...combsWithFirst];
}

console.log(combinations([1, 2, 3]));

So what could be the c version?

EDIT: the version I have so far, but is not working correctly:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    int *values;
    size_t size;
} comb;

comb *combinations;
size_t depth;
int count;

void init()
{
    count = 1; // number of combintations so far
    int size = depth;
    for (int i = 0; i < depth; i++)
    {
        size *= 2;
    }
    combinations = malloc(sizeof(comb) * size);
}

comb *ctor(int *values, size_t size)
{
    comb *newone = malloc(sizeof(comb));
    newone->values = values;
    newone->size = size;
    return newone;
}

comb *pop_front(comb x)
{
    int newSize = x.size - 1;
    int *newVals = malloc(sizeof(int) * newSize);
    memcpy(newVals, x.values + sizeof(int), newSize);
    return ctor(newVals, newSize);
}

comb *push_back(comb x, int newValue)
{
    int newSize = x.size + 1;
    int *newVals = malloc(sizeof(int) * newSize);
    memcpy(newVals, x.values, x.size * sizeof(int));
    newVals[newSize - 1] = newValue;
    return ctor(newVals, newSize);
}

void addComb(comb *x, comb y)
{
}

comb *func(comb *elements)
{
    if (!depth)
    {
        return ctor(NULL, 0);
    }
    int firstEl = elements->values[0];
    comb *rest = pop_front(*elements);

    depth--;
    comb *combsWithoutFirst = func(rest);
    comb *combsWithFirst = ctor(NULL, 0);

    for (int i = 0; i < count; i++)
    {
        comb *combWithFirst = push_back(combsWithoutFirst[i], firstEl);
        // now add that combWithFirst to the combsWithFirst
    }

    // merge the two arrays
}

int main()
{
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁的年少不轻狂 2025-01-24 00:42:04

一种简单的方法是使用位集。我想 64 位已经足够了。

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

void comb(int *set, size_t n) {
    assert(n < 64);
    
    uint64_t bits = 0;
    uint64_t end = 1 << n;
    while (bits < end) {
        printf("[");
        for (size_t i = 0; i < n; ++i) {
            if (bits & (1 << i)) {
                printf("%d ", set[i]);
            }
        }
        printf("]\n");

        bits++;
    }
}

int main(void) {
    int set[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    comb(set, 10);

    return 0;
}

One simple way to do this is using a bitset. I guess 64 bits is far enough.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

void comb(int *set, size_t n) {
    assert(n < 64);
    
    uint64_t bits = 0;
    uint64_t end = 1 << n;
    while (bits < end) {
        printf("[");
        for (size_t i = 0; i < n; ++i) {
            if (bits & (1 << i)) {
                printf("%d ", set[i]);
            }
        }
        printf("]\n");

        bits++;
    }
}

int main(void) {
    int set[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    comb(set, 10);

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文