【发布时间】:2018-06-14 18:02:06
【问题描述】:
我有大量列表(在大多数情况下 > 1,000,000),这些列表被划分为 n x n 网格。这些列表有一些坐标。我定义了点之间的相邻关系——如果它们在彼此的范围内,它们就是“邻居”并放入一个“集群”中。我们可以将小区添加到这些集群中,因此小区 A 是小区 B 的邻居,B 是 C 的邻居,C 不是 A 的邻居。A、B 和 C 将在同一个集群。
鉴于该背景,我有以下代码尝试将点分配给 Python 3.6 中的集群:
for i in range(n):
for j in range(n):
tile = image[i][j]
while tile:
cell = tile.pop()
cluster = create_and_return_cluster(cell, image_clusters[i][j], (i, j))
clusterise(cell, cluster, (i, j), image, n, windows, image_clusters)
def clusterise(cell, cluster, tile_index, image, n, windows, image_clusters):
neighbouring_windows, neighbouring_indices = get_neighbouring_windows(tile_index[0], tile_index[1], n, windows)
neighbours = get_and_remove_all_neighbours(cell, image, tile_index, neighbouring_windows, neighbouring_indices)
if neighbours:
for neighbour, (n_i, n_j) in neighbours:
add_to_current_cluster(cluster, image_clusters, neighbour, (n_j, n_j))
clusterise(neighbour, cluster, (n_i, n_j), image, n, windows, image_clusters)
由于列表规模庞大,我遇到了 RecursionError 问题,并且一直在互联网上搜索有关尾递归的建议。问题是这个算法需要从邻居分支来获取那些邻居的邻居,等等。正如你可以想象的那样,就堆栈帧而言,这很快就会变得相当大。
我的问题是:是否有可能使该算法使用尾递归,或者如何使其成为尾递归?我知道 cluster 参数在这种情况下本质上是一个累加器,但考虑到列表如何缩小以及 clusterise() 中令人讨厌的 for 循环,我不确定如何成功转换为尾递归。有没有人有任何想法?最好有解释支持。
注意:我很清楚 Python 默认不会优化尾递归,是的,我知道其他语言会优化尾递归。我的问题是在这种情况下是否可以使用 Python 来完成。如果我不是绝对必要的话,我不想改变,而且我的许多其他代码已经在 Python 中了。
【问题讨论】:
-
所以使用队列或堆栈。你这里没有尾递归。
-
递归有多深?我没有看到锚。
-
@fafl 与它所在的集群的大小一样深——这显然是可变的。如果没有邻居,则终止。请注意,由于删除了单元格,因此两个单元格不会“竞争”到同一个邻居。
-
尾递归不是语言特性。 Python 很好地支持尾递归。 Python 不 和其他一些语言 做 的是优化 尾递归函数。这是一个很大的区别。见What Is Tail Call Optimization? 和Does Python optimize tail recursion?
标签: python recursion iteration