Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在优化过程中,这种行为的根本原因是什么;“岛屿数量”;使用DFS递归方法编程_C_Recursion_Optimization - Fatal编程技术网

C 在优化过程中,这种行为的根本原因是什么;“岛屿数量”;使用DFS递归方法编程

C 在优化过程中,这种行为的根本原因是什么;“岛屿数量”;使用DFS递归方法编程,c,recursion,optimization,C,Recursion,Optimization,我在优化我从网上下载的“岛屿数量”程序时遇到了一个问题。我试图优化它,如下所述,但不能得到100%的权利 岛的数目是多少 我从一个网站上获取了下面的“c”程序,用于确定给定图表中的岛屿数量 void DFS(int M[][COL], int row, int col, bool visited[][COL]) { // These arrays are used to get row and column numbers of 8 neighbours // of a give

我在优化我从网上下载的“岛屿数量”程序时遇到了一个问题。我试图优化它,如下所述,但不能得到100%的权利

岛的数目是多少

我从一个网站上获取了下面的“c”程序,用于确定给定图表中的岛屿数量

void DFS(int M[][COL], int row, int col, bool visited[][COL])
{
   // These arrays are used to get row and column numbers of 8 neighbours 
   // of a given cell
   static int rowNbr[] = {-1, -1, -1,  0, 0,  1, 1, 1};
   static int colNbr[] = {-1,  0,  1, -1, 1, -1, 0, 1};

   int k = 0;
   // Mark this cell as visited
   visited[row][col] = true;
   printf("\n row=%d, col=%d", row, col); 

   // Recur for all connected neighbours
   for (k = 0; k < 8; ++k) {
       printf(" k=%d", k); 
       if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited) )
           DFS(M, row + rowNbr[k], col + colNbr[k], visited);
   }
}

// The main function that returns count of islands in a given boolean
// 2D matrix
int countIslands(int M[][COL])
{
    // Make a bool array to mark visited cells.
    // Initially all cells are unvisited
    bool visited[ROW][COL];
    memset(visited, 0, sizeof(visited));

    // Initialize count as 0 and travese through the all cells of
    // given matrix
    int count = 0;
    int i = 0, j=0;
    for (i = 0; i < ROW; ++i) {
        for (j = 0; j < COL; ++j) {
            if (M[i][j] && !visited[i][j]) // If a cell with value 1 is not
            {                         // visited yet, then new island found
               DFS(M, i, j, visited);     // Visit all cells in this island.
               ++count;                   // and increment island count
               printf("\n count is %d", count);
            }
        }
        printf("\n");
    }

    return count;
}


// A function to check if a given cell (row, col) can be included in DFS
int isSafe(int M[][COL], int row, int col, bool visited[][COL])
{
    // row number is in range, column number is in range and value is 1 
    // and not yet visited
    printf(" (i=%d, j=%d)", row, col);
    return (row >= 0) && (row < ROW) &&     
       (col >= 0) && (col < COL) &&      
       (M[row][col] && !visited[row][col]); 
} 
下面是我观察到的一件我无法构建逻辑的事情

在我的程序中,我看到下面来自我的程序的代码片段在函数DFS_new中被执行了8次以上,而没有再次调用这个函数(我的意思是甚至没有调用递归函数)


希望这个问题对本论坛有意义,并期待得到积极回应

伟大的反优化

对于整数类型,取消引用指针实际上比按值调用要慢

如果
i
仅为读取且从未在循环内通过引用传递,编译器知道如何展开(int i=0;i形式的循环并将其矢量化

当(i时,它们遇到了形式为
的循环问题,特别是当
i
作为非
常量
引用传递给其他函数时


至于你的错误在哪里:

       (*row) = (*row)+rowNbr[k];
       (*col) = (*col)+colNbr[k];
您正在修改每个循环迭代中的实际整数,并且邻域的偏移现在是累积的,而不是一个接一个地采样

或者换句话说,您不再检查正方形


实际的优化是使
静态
偏移表满
常量
(字段
常量int
),并删除所有调试输出

使用扁平数组(
boolm[ROW][COL]
)而不是数组数组(
boolm[][COL]

关于参数的
const
要正确

对不打算导出到其他编译单元的函数使用
static
关键字

这使得编译器能够进行优化,而且它比您所能做的要好得多:

#include <cstring>

const int COL = 8;
const int ROW = 8;

// A function to check if a given cell (row, col) can be included in DFS
static int isSafe(const bool M[ROW][COL], const int row, const int col, const bool visited[ROW][COL])
{
    // row number is in range, column number is in range and value is 1 
    // and not yet visited
    return (row >= 0) && (row < ROW) &&     
       (col >= 0) && (col < COL) &&      
       (M[row][col] && !visited[row][col]); 
} 

static void DFS(const bool M[ROW][COL], const int row, const int col, bool visited[ROW][COL])
{
   // These arrays are used to get row and column numbers of 8 neighbours 
   // of a given cell
   const int rowNbr[] = {-1, -1, -1,  0, 0,  1, 1, 1};
   const int colNbr[] = {-1,  0,  1, -1, 1, -1, 0, 1};

   int k = 0;
   // Mark this cell as visited
   visited[row][col] = true;

   // Recur for all connected neighbours
   for (k = 0; k < 8; ++k) {
       if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited) )
           DFS(M, row + rowNbr[k], col + colNbr[k], visited);
   }
}

// The main function that returns count of islands in a given boolean
// 2D matrix
int countIslands(const bool M[ROW][COL])
{
    // Make a bool array to mark visited cells.
    // Initially all cells are unvisited
    bool visited[ROW][COL];
    memset(visited, 0, sizeof(visited));

    // Initialize count as 0 and travese through the all cells of
    // given matrix
    int count = 0;
    int i = 0, j=0;
    for (i = 0; i < ROW; ++i) {
        for (j = 0; j < COL; ++j) {
            if (M[i][j] && !visited[i][j]) // If a cell with value 1 is not
            {                         // visited yet, then new island found
               DFS(M, i, j, visited);     // Visit all cells in this island.
               ++count;                   // and increment island count
            }
        }
    }

    return count;
}
#包括
常数int COL=8;
const int ROW=8;
//用于检查给定单元格(行、列)是否可以包含在DFS中的函数
静态int isSafe(const bool M[ROW][COL],const int ROW,const int COL,const bool已访问[ROW][COL])
{
//行数在范围内,列数在范围内,值为1
//还没来过
返回(行>=0)&(行<行)&
(col>=0)和(col

编译“优化”代码,例如使用最新的CLANG 5.0和
-O3
,所有循环都会在程序集中消失。完全被展开的代码或纯向量指令取代:

伟大的反优化

对于整数类型,取消引用指针实际上比按值调用要慢

如果
i
仅为读取且从未在循环内通过引用传递,编译器知道如何展开(int i=0;i
形式的循环并将其矢量化

当(i时,它们遇到了形式为
的循环问题,特别是当
i
作为非
常量
引用传递给其他函数时


至于你的错误在哪里:

       (*row) = (*row)+rowNbr[k];
       (*col) = (*col)+colNbr[k];
您正在修改每个循环迭代中的实际整数,并且邻域的偏移现在是累积的,而不是一个接一个地采样

或者换句话说,您不再检查正方形


实际的优化是使
静态
偏移表满
常量
(字段
常量int
),并删除所有调试输出

使用扁平数组(
boolm[ROW][COL]
)而不是数组数组(
boolm[][COL]

关于参数的
const
要正确

对不打算导出到其他编译单元的函数使用
static
关键字

这使得编译器能够进行优化,而且它比您所能做的要好得多:

#include <cstring>

const int COL = 8;
const int ROW = 8;

// A function to check if a given cell (row, col) can be included in DFS
static int isSafe(const bool M[ROW][COL], const int row, const int col, const bool visited[ROW][COL])
{
    // row number is in range, column number is in range and value is 1 
    // and not yet visited
    return (row >= 0) && (row < ROW) &&     
       (col >= 0) && (col < COL) &&      
       (M[row][col] && !visited[row][col]); 
} 

static void DFS(const bool M[ROW][COL], const int row, const int col, bool visited[ROW][COL])
{
   // These arrays are used to get row and column numbers of 8 neighbours 
   // of a given cell
   const int rowNbr[] = {-1, -1, -1,  0, 0,  1, 1, 1};
   const int colNbr[] = {-1,  0,  1, -1, 1, -1, 0, 1};

   int k = 0;
   // Mark this cell as visited
   visited[row][col] = true;

   // Recur for all connected neighbours
   for (k = 0; k < 8; ++k) {
       if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited) )
           DFS(M, row + rowNbr[k], col + colNbr[k], visited);
   }
}

// The main function that returns count of islands in a given boolean
// 2D matrix
int countIslands(const bool M[ROW][COL])
{
    // Make a bool array to mark visited cells.
    // Initially all cells are unvisited
    bool visited[ROW][COL];
    memset(visited, 0, sizeof(visited));

    // Initialize count as 0 and travese through the all cells of
    // given matrix
    int count = 0;
    int i = 0, j=0;
    for (i = 0; i < ROW; ++i) {
        for (j = 0; j < COL; ++j) {
            if (M[i][j] && !visited[i][j]) // If a cell with value 1 is not
            {                         // visited yet, then new island found
               DFS(M, i, j, visited);     // Visit all cells in this island.
               ++count;                   // and increment island count
            }
        }
    }

    return count;
}
#包括
常数int COL=8;
const int ROW=8;
//用于检查给定单元格(行、列)是否可以包含在DFS中的函数
静态int isSafe(const bool M[ROW][COL],const int ROW,const int COL,const bool已访问[ROW][COL])
{
//行数在范围内,列数为i
       (*row) = (*row)+rowNbr[k];
       (*col) = (*col)+colNbr[k];
#include <cstring>

const int COL = 8;
const int ROW = 8;

// A function to check if a given cell (row, col) can be included in DFS
static int isSafe(const bool M[ROW][COL], const int row, const int col, const bool visited[ROW][COL])
{
    // row number is in range, column number is in range and value is 1 
    // and not yet visited
    return (row >= 0) && (row < ROW) &&     
       (col >= 0) && (col < COL) &&      
       (M[row][col] && !visited[row][col]); 
} 

static void DFS(const bool M[ROW][COL], const int row, const int col, bool visited[ROW][COL])
{
   // These arrays are used to get row and column numbers of 8 neighbours 
   // of a given cell
   const int rowNbr[] = {-1, -1, -1,  0, 0,  1, 1, 1};
   const int colNbr[] = {-1,  0,  1, -1, 1, -1, 0, 1};

   int k = 0;
   // Mark this cell as visited
   visited[row][col] = true;

   // Recur for all connected neighbours
   for (k = 0; k < 8; ++k) {
       if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited) )
           DFS(M, row + rowNbr[k], col + colNbr[k], visited);
   }
}

// The main function that returns count of islands in a given boolean
// 2D matrix
int countIslands(const bool M[ROW][COL])
{
    // Make a bool array to mark visited cells.
    // Initially all cells are unvisited
    bool visited[ROW][COL];
    memset(visited, 0, sizeof(visited));

    // Initialize count as 0 and travese through the all cells of
    // given matrix
    int count = 0;
    int i = 0, j=0;
    for (i = 0; i < ROW; ++i) {
        for (j = 0; j < COL; ++j) {
            if (M[i][j] && !visited[i][j]) // If a cell with value 1 is not
            {                         // visited yet, then new island found
               DFS(M, i, j, visited);     // Visit all cells in this island.
               ++count;                   // and increment island count
            }
        }
    }

    return count;
}