【转载】FloodFill算法的优化

FLoodFill算法名为“洪水填充算法”,根据在网上所看到的解释,大概也就是找到一个可以访问的点,接着进行DFS或BFS,但是用DFS似乎效率不高,BFS又比较难写,这样还不如直接一遍DFS或BFS呢!于是我就想到了另一种实现的方法,但是因为我也不太清楚FloodFill的具体实现,所以可能这个算法有一点雷同。
这个算法可以不断扩展找多个联通块,但是可能需要用并查集来维护多个联通块,所以可能有点麻烦。而只能找一个联通块的代码可以作为基础,相应的多个联通块的也不难写。这个优化比起DFS和BFS相较而下最大的优势就是从O(N!)左右的复杂度降到了O(n^2),而且几乎不占用内存空间,常数还比较小,比BFS好写了不知多少倍。
这个优化算法的基本思想是这样的:首先一个二重循环遍历整个图,如果所遍历到的节点的旁边有遍历过的节点,则自动联通。
 
    

const int MAXN = 1001;
const int dx[] = {1,0,-1,0};
const int dy[] = {0,1,0,-1};
int N; //图的大小
bool Graph[MAXN][MAXN];
bool isGo[MAXN][MAXN];

for (int i=0;i!=N;++i){
for (int j=0;j!=N;++j){
for (int k=0;k!=4;++k){
if (isGo[i+dx[k]][j+dy[k]] && Graph[i+dx[k]][j+dy[k]]){
//做一些相应的事
}
}
isGo[i][j] = true;
}
}

这个算法的时间复杂度确实是O(n^2),但是可以再加优化。比如说我们现在已经知道了开始查找的点,也就是联通块中的第一个点(最左上角的点),这是我们如果遇到有一行的点都没有碰到旁边的点有访问过的,那就可以直接break出去,因为这样的话下面就再没有点可以与其联结了。
不过考虑再像这样的情况,那张图是这样的:(1表示能走,0,表示不能走)
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 
1 0 0 0 0 0 0 0 0 0 
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0

这样的话就虽然显然能够优化,但是仍然达到了最坏的复杂度O(n^2),无法中途退出。

所以,我就研究出了这样的一种算法,称为行列联合FloodFill。顾名思义,就是交叉地搜索列和行,如果有连续无法搜索到时就直接停止了。当然如果直接扫描,会有一定的重复,所以可以不断减少列和行的访问长度,从而达到期望上的平均最优化。
很好理解吧?所以,这就是我所研究出的一种FloodFill算法的高效实现(尽管可能没有什么用处)。

你可能感兴趣的:(【转载】FloodFill算法的优化)