递归函数中的计数器

3 投票
5 回答
3951 浏览
提问于 2025-04-17 08:21

我刚开始学习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 个回答

2

你得到的结果是正常的

更新:我之前的解释(下面的内容)并不完全正确。(感谢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)
3

所以这个 floodcount() 函数是返回一个新的 count 值。但是你从来没有把它存起来或者使用它 :)

把像下面这样的代码:

floodcount(x+1, y-1, array, value, count)

替换成:

count = floodcount(x+1, y-1, array, value, count)
2

除了之前解决的计数问题:

你可以通过每次都进行所有的递归调用来减少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

撰写回答