如何有效地遍历以2为底的向量

时间:2019-12-13 15:58:28

标签: c loops vector binary

我需要编写一个程序,以遍历base-2(二进制)矢量的所有可能组合。如果此向量的大小为3,则可以使用三个嵌套循环来完成此操作,如下所示:

bool array[3];
for(int i = 0; i < 2; i++)
{
    for(int j = 0; j < 2; j++)
    {
        for(int k = 0; k < 2; k++)
        {
            array[0] = i;
            array[1] = j;
            array[2] = k;
        }
    }
}

但是问题是在我的应用程序中,数组大小是可变的,并且基本上可以是任何数字。如果要查找12位向量的所有值,则不想编写12个嵌套循环,因此使用上面的代码是不可维护的。相反,我想出了以下解决方案:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

#define SIZE    12

int main(void)
{
    bool array[SIZE];
    for(int i = 0; i < SIZE; i++) array[i] = 1;
    int max_num = pow(2, SIZE);

    for(int i = 0; i < max_num; i++)
    {
        if(array[0] == 0) array[0]++;
        else
        {
            array[0] = 0;
            for(int j = 1; j < SIZE; j++)
            {
                if(array[j] == 1) array[j] = 0;
                else
                {
                    array[j] = 1;
                    break;
                }
            }
        }
        for(int j = 0; j < SIZE; j++)
        {
            printf("%d", array[j]);
            if(j != SIZE - 1) printf(", ");
            else printf("\n");
        }
    }
}

对于我来说,相对如此简单的事情,这似乎仍然是很多代码。我的问题是:有没有更有效的方法?

2 个答案:

答案 0 :(得分:1)

您对数组所做的事情实际上是对数组表示的数字进行递增(加一)。 让我们将增量留给编译器,并使用整数中的位。

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

#define SIZE    12

int main(void)
{
    bool array[SIZE];
    int max_num = 1 << SIZE;

    for(int i = 0; i < max_num; i++)
    {
        for(int j = 0; j < SIZE; j++)
        {
            array[j] = (i >> j) & 1;
        }
        for(int j = 0; j < SIZE; j++)
        {
            printf("%d", array[j]);
            if(j != SIZE - 1) printf(", ");
            else printf("\n");
        }
    }
}

答案 1 :(得分:1)

正如其他人指出的那样,它实际上是在增加二进制数。但是,出于原始代码的精神,我决定不使用本地加法/增量运算符来增加向量的“欺骗”,并提出了以下建议:

#include <stddef.h>
#include <stdbool.h>

bool first(size_t size, bool array[size])
{
    size_t i;

    for (i = 0; i < size; i++)
    {
        array[i] = 0;
    }
    return i > 0;
}

bool next(size_t size, bool array[size])
{
    size_t i;

    for (i = 0; i < size && array[i]; i++)
    {
        array[i] = 0;
    }
    if (i < size)
    {
        array[i] = 1;
        return 1;
    }
    return 0;
}

#include <stdio.h>

int main(void)
{
    enum { SIZE = 12 };
    bool array[SIZE];
    bool going;

    for (going = first(SIZE, array); going; going = next(SIZE, array))
    {
        size_t i;

        for (i = 0; i < SIZE - 1; i++)
        {
            printf("%d, ", array[i]);
        }
        printf("%d\n", array[i]);
    }
    return 0;
}

可以轻松地在其他基地工作:

#include <stddef.h>
#include <stdbool.h>

bool first(size_t size, unsigned int array[size])
{
    size_t i;

    for (i = 0; i < size; i++)
    {
        array[i] = 0;
    }
    return i > 0;
}

bool next(size_t size, unsigned int array[size], unsigned int base)
{
    size_t i;

    for (i = 0; i < size && array[i] == base - 1; i++)
    {
        array[i] = 0;
    }
    if (i < size)
    {
        array[i]++;
        return 1;
    }
    return 0;
}

#include <stdio.h>

int main(void)
{
    enum { SIZE = 5 };
    enum { BASE = 3 };
    unsigned int array[SIZE];
    bool going;

    for (going = first(SIZE, array); going; going = next(SIZE, array, BASE))
    {
        size_t i;

        for (i = 0; i < SIZE - 1; i++)
        {
            printf("%u, ", array[i]);
        }
        printf("%u\n", array[i]);
    }
    return 0;
}