C 在优化过程中,这种行为的根本原因是什么;“岛屿数量”;使用DFS递归方法编程
我在优化我从网上下载的“岛屿数量”程序时遇到了一个问题。我试图优化它,如下所述,但不能得到100%的权利 岛的数目是多少 我从一个网站上获取了下面的“c”程序,用于确定给定图表中的岛屿数量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
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
作为非常量
引用传递给其他函数时
至于你的错误在哪里:
(*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;
}