我遇到1使用递归时的分段

时间:2017-11-02 22:38:43

标签: c arrays recursion 2d

我应该使用递归来检查所有邻居,比如Moore的邻居,并检查随机生成的数组,以查找使用Moore邻居连接的所有1。我的递归代码在遇到零时似乎工作得很好,但是当它遇到一个时它会给我一个分段错误。我试过gdb和valgrind,但它给了我这个错误。

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a34 in recursive (arr=0x6030b0, xcoord=-1, 
ycoord=0, row=6, 
    col=6) at as4.c:79
79          if(arr[xcoord][ycoord] == 1)

当我在gdb()中键入的位置:我得到了这个

#0  0x0000000000400a34 in recursive (arr=0x6030b0, xcoord=-1, 
ycoord=0, row=6, 
col=6) at as4.c:79

#1  0x0000000000400a61 in recursive (arr=0x6030b0, xcoord=0, 
ycoord=0, row=6, 
col=6) at as4.c:83

#2  0x0000000000400975 in main (argc=3, argv=0x7fffffffdf48) at 
as4.c:56

所以我不确定我是在做错了什么,或者我的递归是不是错了。有人能告诉我我做错了吗?

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

int recursive(int **arr, int xcoord, int ycoord, int row, int col);//What are the arguments for the recursive function?

int main(int argc, char** argv)
{
    int i;//counters
    int j;//counters
    int xcoord;//x coordinate input
    int ycoord;//y coordinate input

    //random number generator thing idk lol
    srand((unsigned int)time(NULL));

    int row = strtol(argv[1], NULL, 0);//ROW from command line arguments (1st number)
    int col = strtol(argv[2], NULL, 0);//COL from command line arguments (2nd number)

    int *arrStorage = malloc(row * col * sizeof(int));//dynamically allocating memory for 2d array
    int **arr = malloc(row * sizeof(int));        //pointer to pointer to array or whatever

    //intializing array
    for (i = 0; i < row; i++)
    {
            arr[i] = arrStorage + col * i;
    }

    //printing out 2d array
        for (i = 0; i <  row; i++)
    {
            for (j = 0; j < col; j++)
        {
            arr[i][j] = rand() % 2;
            printf("%d\t", arr[i][j]);
        }

        printf("\n");
    }

    printf(" ");

    //Exit the function when non number is entered
    //Otherwise continue
    while(1)
    {
        printf("Enter coordinate i,j (Non numeric to quit) \n");    

        if(1!=scanf("%d", &xcoord) || 1!=scanf("%d", &ycoord))
        {
            return 0;
        }

        printf("Blob size: %d\n", recursive(arr, xcoord, ycoord, row, col));
        printf("The total size it takes up is %d percent \n", recursive(arr, xcoord, ycoord, row, col)/(row*col));
    }

    for (i = 0; i < row; i++)
    {
        free(arr[i]);
    }
}

int recursive(int **arr, int xcoord, int ycoord, int row, int col)
{
    int blobsize = 0;

    //if coordinate is out of bounds or the user puts in too small or big coordinate return 0
    if(xcoord < 0 && ycoord < 0 && xcoord > row && ycoord > col)
    {
        return 0;
    }

    //recursively check all the neighbors
    else
    {
        if(arr[xcoord][ycoord] == 1)
        {
            blobsize = blobsize + 1;

            if(recursive(arr, xcoord - 1, ycoord, row, col))//Check up
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;
            }

            if(recursive(arr, xcoord - 1, ycoord + 1, row, col))//Check right up
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;
            }

            if(recursive(arr, xcoord, ycoord + 1, row, col))//Check right
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;
            }

            if(recursive(arr, xcoord + 1, ycoord + 1, row, col))//Check bottom right
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;
            }

            if(recursive(arr, xcoord + 1, ycoord, row, col))//Check bottom
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;   
            }

            if(recursive(arr, xcoord + 1, ycoord-1, row, col))
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;
            }

            if(recursive(arr, xcoord, ycoord-1, row, col))
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;
            }

            if(recursive(arr, xcoord - 1, ycoord - 1, row, col))
            {
                if(arr[xcoord][ycoord] == 1)
                {
                    blobsize = blobsize + 1;
                }
                return 1;
            }       
        }
    }

    return blobsize;
}

是的,如果我在某个位置遇到1,我必须使用递归检查我的所有邻居并将blobsize增加1。

2 个答案:

答案 0 :(得分:0)

您的递归永远不会结束,程序会因为stackoverflow而失败。例如,对于6x6,它将检查......(4,4),(5,5),(4,4),(5,5)...无休止地调用recursive,炸毁堆栈

此外,free两个指针都是

free(arrStorage)
free(arr)

因为libc / kernel不知道如何free(a[i])

答案 1 :(得分:0)

一个非常好的方法(这很容易优化,因为你可以构建队列而不是使用递归)是使用所谓的三色算法。

http://www.cs.cornell.edu/courses/cs2112/2012sp/lectures/lec24/lec24-12sp.html

基本上你:

1)标记您正在搜索白色的所有正方形

2)从白色方块开始: - 标记为方形黑色 - 将其所有邻居(相同类型)标记为灰色并将它们放在队列的末尾

3)从队列前面抓一个灰色方块: - 标记为黑色 - 将所有白色邻居标记为灰色并将它们放在队列的末尾

在队列中有方格时执行/。

计算黑色方块,这是你连接的blob

注意:这会创建一个带有常量的着色。在每次迭代之后,将不会有与白色方块相邻的黑色方块。 该算法在O(n)

中运行