【发布时间】:2017-06-20 23:59:28
【问题描述】:
我了解递归的基本原理,在处理诸如计算数字的阶乘之类的简单事情时一点也不混乱,这是递归的最基本用法。但是,当您开始在更复杂的环境中使用递归时,它开始让我感到非常困惑。
在我的例子中,我想创建一个函数,它使用“合并排序”的方式对列表中的项目进行排序,使用递归。所以我开始工作了,这就是我第一次尝试时想出的(不是我必须纠正一些错别字):
def merge_sort(ls):
size = len(ls)
if size <= 1:
return ls
left = merge_sort(ls[:size/2])
right = merge_sort(ls[size/2:])
return merge(left, right)
def merge(left, right):
ls = []
ln1 = len(left)
ln2 = len(right)
length = ln1 + ln2
while length > 0:
if not left:
ls.append(right.pop(0))
length -= 1
elif not right:
ls.append(left.pop(0))
length -= 1
else:
if left[0] < right[0]:
ls.append(left.pop(0))
length -= 1
elif right[0] < left[0]:
ls.append(right.pop(0))
length -= 1
return ls
print merge_sort([8,5,4,6,1])
我点击了运行,它起作用了,但我不明白它为什么起作用。是的,我创建了一段代码,但我不明白为什么。
所以 "merge_sort" 将列表分成两部分,直到有一个包含单个项目的简单列表。它使用递归来实现这一点,当我们得到一个包含单个项目的简单列表时,它会将其分配给一个新列表,即 left 或 right。然后我在 "merge" 函数中使用这两个新列表对它们进行排序并以正确的方式将它们合并在一起。到目前为止一切顺利,但是当我点击“执行”时,我所期望的是代码在前 2 个项目处停止并打印一个包含 2 个已排序项目的小列表。然而 "merge_sort" 仍在继续。即使我相信它应该在执行后结束:
return merge(left, right)
现在这是我的问题。为什么会回到"merge_sort" 的开头,如何保存旧值而不破坏由"merge" 生成的新排序“小列表”?我希望我的问题对你有意义。
感谢大家的帮助!
【问题讨论】:
-
听起来您在询问call stack,或者更具体地说,在这种情况下是recursive stack。阅读它们以了解这里发生的递归。
-
在原始的
merge_sort([8,5,4,6,1])调用返回之前不会打印任何内容。但在此之前,两个子列表上的两个merge_sorts 必须返回。但在 那 发生之前,每个子列表的子列表上的merge_sorts 必须返回。等等,直到你得到零个或一个元素子列表的基本情况。顺便说一句,如果您想在包含重复项目的列表上安全地使用您的算法,则需要对其进行调整。考虑left[0] == right[0]时会发生什么。
标签: python list sorting recursion