在standard algorithm for connected component counting中,使用了称为union-find的不相交集数据结构。在
为什么要使用这种数据结构?我编写了一些代码来线性搜索图像,维护两个线性缓冲区来存储每个连接像素的当前和下一个组件计数,方法是检查四个邻居(E、SE、S、SW),并且在连接的情况下,更新连接映射以将较高的组件与较低的组件连接起来。 完成后,搜索所有未连接的零部件并报告计数。在
我只是不明白为什么这种方法比使用union find效率低。在
这是我的密码。输入文件已缩减为0
s和1
s。程序输出由0
s组成的连接组件的数量
def CompCount(fname):
fin = open(fname)
b,l = fin.readline().split()
b,l = int(b),int(l)+1
inbuf = '1'*l + fin.read()
prev = curr = [sys.maxint]*l
nextComp = 0
tree = dict()
for i in xrange(1, b+1):
curr = [sys.maxint]*l
for j in xrange(0, l-1):
curr[j] = sys.maxint
if inbuf[i*l+j] == '0':
p = [prev[j+n] for m,n in [(-l+1,1),(-l,0),(-l-1,-1)] if inbuf[i*l + j+m] == '0']
curr[j] = min([curr[j]] + p + [curr[j-1]])
if curr[j] == sys.maxint:
nextComp += 1
curr[j] = nextComp
tree[curr[j]] = 0
else:
if curr[j] < prev[j+1]: tree[prev[j+1]] = curr[j]
if curr[j] < prev[j]: tree[prev[j]] = curr[j]
if curr[j] < prev[j-1]: tree[prev[j-1]] = curr[j]
if curr[j] < curr[j-1]: tree[curr[j-1]] = curr[j]
prev = curr
return len([x for x in tree if tree[x]==0])
我没有完全理解你的问题,把它写清楚并组织好你的问题,对你自己真的有好处。在
我的理解是,你想在0-1图像中使用8邻域来标记连接的组件。如果是这样的话,你假设得到的邻域图是平面的,这是错误的。你在“对角线”有十字路口。在这样的图像中构造K{3,3}或K{5}应该很容易。在
我的变体:
一开始,你的节点将是各自的集合
随着算法的进展和集合的合并,它的输入相对减少了一半。在
在这个例子中,我正在检查一些图形中的组件。在将所有边合并到它们的最大可能集合之后,我只剩下3个集合,给出了3个断开的组件。 (组件数是算法完成时可以获得的集合数。)
一个可能的图形(对于上面的树):
^{pr2}$你的算法有缺陷。考虑这个例子:
你的算法有2个组件,而它只有1个组件。在
为了测试,我使用了您代码的这个稍微修改过的版本。在
^{pr2}$让我试着用文字来解释你的算法(用图形而不是网格)。在
(您的
tree
与我的roots
相同:请注意,您从不使用tree[]
元素的值,只使用它们是否为0。。。这只是实现一个集合)它类似于union find,只是它假定在合并两个组件时,v[]值较高的那个组件以前从未与另一个组件合并。在反例中,这是被利用的,因为中间列中的两个0已与其左侧的0合并。在
相关问题 更多 >
编程相关推荐