递归函数中的计数器
我刚开始学习Python和编程。最近我写了一个函数,这个函数会在一个数组中查找相邻的元素,看看它们的值是否相差不超过0.05,类似于一种叫做“洪水填充”的算法。唯一的问题是,我在计算这个函数运行了多少次时做了一些愚蠢的事情(我觉得这也能告诉我找到了多少个元素),所以我的计数值是错误的。虽然代码在找到相邻元素方面是有效的,但计数的结果却有点奇怪。
def floodcount (x,y,array,value,count=0): #akin to a bucket fill in paint, finds the area instead
nrows = len(array)-1 #rows of the image
ncols = len(array[0])-1 #columns of the image
diff = array[x][y] - value
if (diff < 0.00) or (diff > 0.05): # the base case, finding a diff more than 0.05 or less than 0 is like finding a boundary
return 0
count = count +1
print 'count1 ',count
array[x][y] = -5 # so we do no calculate this pixel again
#print "[",x,",",y,"]"
if x > 0:
#print '1'# if not the first elemnet then can go back, this makes sure that x is within the array all the time
floodcount (x-1,y,array,value,count)
if y > 0:
#print '2'
floodcount (x,y-1,array,value,count)
if x < nrows:
#print '3'
floodcount (x+1,y,array,value,count)
if y < ncols:
#print '4'
floodcount (x,y+1,array,value,count)
if x > 0 and y > 0:
#print '5'
floodcount (x-1,y-1,array,value,count)
if x < nrows and y < ncols:
#print '6'
floodcount (x+1,y+1,array,value,count)
if x <nrows and y > 0:
#print '7'
floodcount (x+1,y-1,array,value,count)
if x > 0 and y < ncols:
#print '8'
floodcount (x-1,y+1,array,value,count)
print 'count2 ',count
return count
举个测试例子:
数组 = [[5,1,1,3,4],[4,5,6,2,5],[5,8,5,5,9]]
x=0 和 y=0
输出结果:
count1 1
count1 2
count1 3
count1 4
count1 5
count2 5
count2 4
count2 3
count1 3
count2 3
count2 2
count2 1
从这些输出可以看出,似乎有什么地方不对劲 :P
有没有人能指出我哪里做错了?任何帮助都非常感谢。
5 个回答
你得到的结果是正常的
更新:我之前的解释(下面的内容)并不完全正确。(感谢Ben的指正)。不过,我提出的解决方案是对的。
在递归调用中,计数参数是按值传递的,而不是按引用传递。这意味着你在子调用中所做的增量操作不会影响当前函数中的计数变量(也就是局部变量)。
你可以通过使用全局变量来实现想要的结果:
count = 0
def floodcount (x,y,array,value):
global count
...
或者通过在一个包装类中设置一个计数器(对象是按引用传递的):
class CounterClass:
cnt = 0
def floodcount (x,y,array,value, counter):
...
counter.cnt += 1
...
或者:返回你的函数生成的计数器:
count = floodcount(x+1, y-1, array, value, count)
所以这个 floodcount()
函数是返回一个新的 count
值。但是你从来没有把它存起来或者使用它 :)
把像下面这样的代码:
floodcount(x+1, y-1, array, value, count)
替换成:
count = floodcount(x+1, y-1, array, value, count)
除了之前解决的计数问题:
你可以通过每次都进行所有的递归调用来减少if
语句的数量,然后在函数开始时用if x < 0 or y < 0 or x > nrows or y > ncols
来检查数组的边界。
#akin to a bucket fill in paint, finds the area instead
def floodcount (x,y,array,value,count=0):
nrows = len(array)-1 #rows of the image
ncols = len(array[0])-1 #columns of the image
if x < 0 or y < 0 or x > nrows or y > ncols:
return count
diff = array[x][y] - value
# the base case, finding a diff more than 0.05 or less than 0 is like finding a boundary
if (diff < 0.00) or (diff > 0.05):
return count
count = count +1
print 'count1 ',count
array[x][y] = -5 # so we do no calculate this pixel again
#print "[",x,",",y,"]"
count = floodcount (x-1,y,array,value,count)
count = floodcount (x,y+1,array,value,count)
count = floodcount (x+1,y,array,value,count)
count = floodcount (x,y-1,array,value,count)
count = floodcount (x-1,y-1,array,value,count)
count = floodcount (x+1,y+1,array,value,count)
count = floodcount (x+1,y-1,array,value,count)
count = floodcount (x-1,y+1,array,value,count)
print 'count2 ',count
return count