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算法的相对高效实现(尽管可能没有什么用处),平衡了时间复杂度和空间复杂度,就一个两重循环应该就能够搞定了。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值