我可以加快这个功能吗?

时间:2017-04-15 04:55:59

标签: c performance conways-game-of-life

我试图在C中写下John Conway的生命游戏,但我在向棋盘添加活细胞时遇到了麻烦。我写的处理它的功能非常慢。

思考过程:我想随机添加n个活细胞到板上,所以当细胞留下来活着时,得到一个随机(x,y)对,如果它死了,就让它活着。这样我可以保证n个细胞活着。

我对这个问题的理解不正确,还是我效率低下?为什么这么慢,我怎样才能让它更快?

void add_cells( int board[BOARD_WIDTH][BOARD_HEIGHT], int n )
{
    //  Randomly set n dead cells to live state.
    while ( n )
    {
        int randX = rand() % BOARD_WIDTH;
        int randY = rand() % BOARD_HEIGHT;

        if( board[randX][randY] == 0 )
        {
            board[randX][randY] = 1;
            n--;
        }
    }
}

4 个答案:

答案 0 :(得分:2)

如果让我们说70%的细胞还活着,那就意味着你的程序必须在10次中找到7次其他细胞,这样就不必重复了。

您可以从剩余的单元格中弹出选定的单元格"将它设置为活动时的数组,并在此数组中随机选择单元格。我建议使用动态可调整大小的容器,这样你就不必操纵整个剩余的细胞了。每次弹出单元格时都会生成数组。这应该有助于节省更多时间。

答案 1 :(得分:0)

如果您的电路板在内存中是连续的,则无需再拨打rand()两次。您可以使用rand() % (BOARD_WIDTH * BOARD_HEIGHT)

void add_cells(uint8_t board[BOARD_WIDTH][BOARD_HEIGHT], int n)
{
    std::mt19937 eng;
    uniform_int_distribution<int> dist(0, BOARD_WIDTH * BOARD_HEIGHT - 1);

    while(n)
    {
        int index = dist(eng);

        uint8_t* cell = (uint8_t*)board + index;
        if(*cell == 0)
        {
            *cell = 1;
            --n;
        }
    }
}

答案 2 :(得分:0)

有几个问题可能会解释您的问题有些缓慢:

  • 在致电add_cells()之前,电路板是否已初始化为0?如果电路板具有随机内容,找到死细胞可能需要很长时间,或者如果少于n个细胞死亡则可能需要永久。

  • 您确定board是否已正确定义? 2D数组似乎更自然,y是第一维,x是第二维:使用int board[BOARD_HEIGHT][BOARD_WIDTH]并交换randXrandY的索引值。< / p>

  • 如果(n > 0)使用否定add_cells()进行调用,n的测试可以防止无限循环。

  • 如果n很大,找到死细胞需要很长时间,因为随机拍摄的几率很小。

  • 如果n大于BOARD_WIDTH * BOARD_HEIGHT或者死区数少于n,则循环将永远迭代。

如果n很大或者电路板只有几个死细胞,那么枚举死细胞并从死细胞中随机选择目标细胞会更有效。缺点是如果n很小并且电路板有很多死区,这种方法会慢一些。

n小的时间复杂度与死区的数量相比是 O(n),这很难被击败,并且在当前的硬件上应该非常快,但它会趋于朝 O(n * BOARD_WIDTH * BOARD_HEIGHT)如果n很大或接近死区的数量, 效率低,且函数从不如果n大于死细胞数,则结束。

  • 如果在调用add_cells()时已知该电路板为空,如果n大于BOARD_WIDTH * BOARD_HEIGHT / 2,则将所有单元设置为活动并选择更高效n要杀死的细胞。

  • 如果电路板不一定是空的,通过此功能,活动单元的数量将有助于确定哪种方法更好,以及是否至少有n个死区,而不需要冗长的循环列举死细胞。

答案 3 :(得分:-2)

模数函数非常慢,请尝试(float)rand()/RAND_MAX*BOARD_WIDTH + 0.5

您也可以使用更快的兰特,请参阅here