【问题标题】:Recursion on a merge sort function is confusing合并排序函数的递归令人困惑
【发布时间】: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" 将列表分成两部分,直到有一个包含单个项目的简单列表。它使用递归来实现这一点,当我们得到一个包含单个项目的简单列表时,它会将其分配给一个新列表,即 leftright。然后我在 "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


【解决方案1】:

这个问题的答案相当广泛。要完全理解这一点,您需要了解 stackbuildup 如何与递归一起工作以及所述 buildup 中的指针如何工作。

这是递归调用的,因为列表需要通过将其分成两半来分解,直到它处于最小可能的单位(余数为 1 或 0)一旦完成,堆栈构建将使用其预定义的指针进行回溯所有以前的调用实例。

这是一个深入的编程语言概念。

有关堆栈构建和回调的更多信息,请参见此处。 https://en.wikipedia.org/wiki/Call_stack

【讨论】:

  • 我想我现在明白了。这就像用列表的每个值创建该函数的其他变体,直到它们中的每一个都取一个最终值。老实说,www.pythontutor.com 帮助我弄清楚那里发生了什么,但我现在有点“开明”了。感谢您的帮助
猜你喜欢
  • 2020-07-30
  • 2015-09-07
  • 2014-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-06
  • 2014-10-11
  • 2021-06-13
相关资源
最近更新 更多