alternative to recursion based merge sort logic
下面是python中的合并排序逻辑:(这是第一部分,忽略函数merge())问题在于将递归逻辑转换为while循环。代码礼貌:rosettacode merge sort
1 2 3 4 5 6 7 8 9 10 11 | def merge_sort(m): if len(m) <= 1: return m middle = len(m) / 2 left = m[:middle] right = m[middle:] left = merge_sort(left) right = merge_sort(right) return list(merge(left, right)) |
是否可以使它在while循环中动态排序,而每个左数组和右数组分成两个,一种指针会根据左数组和右数组的数量不断增加,并将它们断开,直到只剩下一个长度大小的列表?因为每次在左右两侧进行下一个拆分时,数组都会不断分解,直到只剩下一个长度列表为止,因此左侧(左、左、右)和右侧(右、左、右)的拆分次数都会增加,直到所有拆分都达到大小为1的列表。
一个可能的实现可能是:
1 2 3 4 5 6 | def merge_sort(m): l = [[x] for x in m] # split each element to its own list while len(l) > 1: # while there's merging to be done for x in range(len(l) >> 1): # take the first len/2 lists l[x] = merge(l[x], l.pop()) # and merge with the last len/2 lists return l[0] if len(l) else [] |
递归版本中的堆栈帧用于存储逐渐变小的需要合并的列表。您正确地识别出,在堆栈的底部,无论您排序什么,每个元素都有一个元素列表。因此,通过从一系列单元素列表开始,我们可以迭代地构建更大的合并列表,直到我们有一个单独的、排序的列表。
应读卡器的请求,从替代到基于递归的合并排序逻辑重新发布:
消除递归的一种方法是使用队列来管理未完成的工作。例如,使用内置的
1 2 3 4 5 6 7 8 9 10 11 | from collections import deque from heapq import merge def merge_sorted(iterable): """Return a list consisting of the sorted elements of 'iterable'.""" queue = deque([i] for i in iterable) if not queue: return [] while len(queue) > 1: queue.append(list(merge(queue.popleft(), queue.popleft()))) return queue[0] |
据说,每个递归函数都可以用非递归的方式编写,所以简短的回答是:是的,这是可能的。我能想到的唯一解决方案是使用基于堆栈的方法。当递归函数调用自身时,它将一些上下文(其参数和返回地址)放在内部堆栈上,这对您来说是不可用的。基本上,为了消除递归,您需要做的就是编写自己的堆栈,每次您进行递归调用时,都将参数放到这个堆栈上。
有关更多信息,您可以阅读本文,或者参考Robert Lafore的"Java中的数据结构和算法"中的"消除递归"一节(尽管本书中的所有示例都是用Java给出的,但很容易掌握主要思想)。
按照上面丹的解决方案,并接受关于流行音乐的建议,我仍然尝试着消除"while"和其他一些不那么"python"的方法。以下是我建议的解决方案:PS:L= LeN
我对dans解决方案的怀疑是,如果l.pop()和l[x]是相同的,并且产生了冲突,就像在迭代l一半长度后的奇数范围一样?
1 2 3 4 5 6 | def merge_sort(m): L = [[x] for x in m] # split each element to its own list for x in xrange(l(L)): if x > 0: L[x] = merge(L[x-1], L[x]) return L[-1] |
这可以在所有的学术讨论中继续,但我得到了一个替代递归方法的答案。