需要帮助重写非递归算法的递归函数

时间:2017-06-29 07:50:40

标签: python recursion

我发现我无法在我的micropython平台上使用递归,因为这个实现没有堆栈保护,并且继续乐意将函数调用写入堆中。

现在我必须重新编写这个递归的python代码,我仍然没有找到解决方案!

这里有一些解释标志性的地方:

图层 - 如何"深度"递归是,现在。最深层依赖于列表self.blobs,如果layer为len(self.blobs) - 1,则递归应该返回,否则再次递归。

firstID和lastID是用于查明组合是否可行的参数(在self.differenceValid()中找到)

possibleQueues是返回值。 self.possibleLandmarkIDs是一个包含数字的嵌套列表,如:

[[0, 2, 4], [6, 8, 1, 3], [0, 2, 4], [1, 3]]

len(self.blobs)和len(self.possibleLandmarkIDs)相等

如果您有任何疑问,请随时提出。我希望你能帮助我!

def findQueueCombinationsRecursive(self, layer, firstID, lastID):
    possibleQueues = []
    for index in range(len(self.possibleLandmarkIDs[layer])):
        landmarkID = self.possibleLandmarkIDs[layer][index]
        if layer == 0:
            firstID = self.possibleLandmarkIDs[layer][index]
            lastID = self.possibleLandmarkIDs[layer][index]
        if self.differenceValid(firstID, lastID, landmarkID):
            if layer == len(self.blobs) - 1:
                possibleQueues.append([])
                possibleQueues[len(possibleQueues)-1].append(landmarkID)
            else:
                deeperList = self.findQueueCombinationsRecursive(layer + 1, firstID, landmarkID)
                if len(deeperList) == 0:
                    continue
                for item in deeperList:
                    possibleQueues.append([])
                    possibleQueues[len(possibleQueues)-1].append(landmarkID)
                    for i in item:
                        possibleQueues[len(possibleQueues)-1].append(i)
    return possibleQueues

1 个答案:

答案 0 :(得分:0)

您几乎总是可以使用堆栈将递归算法转换为迭代算法。这里快速转换你的代码(使用列表作为堆栈),虽然我可能有一些小错误:

def findQueueCombinationsRecursive(self):
    results = []
    stack = [(0, None, None, [])] # items on the stack are 4-tuples
    while stack:
        layer, first_id, second_id, queue = stack.pop()
        for landmark_id in reversed(self.possibleLandmarkIDs[layer]):
            if layer == 0:
                first_id = second_id = landmark_id
            if self.differenceValid(first_id, second_id, landmark_id):
                new_queue = queue + [landmark_id]
                if layer == len(self.blobs) - 1:
                    results.append(new_queue)
                else:
                    stack.append((layer+1, first_id, landmark_id, new_queue))
    return results

如果您不关心结果所在的顺序是否与递归代码相同,则可以摆脱reversed循环中的for调用。由于堆栈是LIFO(后进先出),我们需要以相反的顺序推送项目,以便按原始顺序将它们从堆栈中弹出。

您可能还会考虑使用截然不同的方法来解决您的问题。例如,我认为您可以使用itertools.product(*self.possibleLandMarkIDs)生成所有可能的队列。然后,您需要通过为每个候选队列的每个步骤调用self.differenceValid方法来过滤掉无效队列。