【问题标题】:Merge Sort Problems - Python合并排序问题 - Python
【发布时间】:2013-02-08 17:14:03
【问题描述】:

我的代码有什么问题?它只打印部分向量值。似乎while循环在某个时候中断。我不明白为什么。

def print_list(vect):
    for i in range(0, len(vect)):
        print(vect[i])

def merge_sort(vect):
    left = []
    right = []    
    result = []

    for i in range(0, int(len(vect)/2)):
        left.append(vect[i])
    for i in range(int(len(vect)/2), len(vect)):
        right.append(vect[i])

    left.sort()
    right.sort()
    i = 0
    j = 0

    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1

    print(len(result))
    return result

vect = [3, 1, 5, 7, 10, 2, 0]

vect = merge_sort(vect)

【问题讨论】:

  • 我不明白你为什么打电话给left.sort()right.sort()。这对列表的每一半都使用 Python 的内部排序函数,这使得您的合并排序实现完全没有意义。

标签: python algorithm sorting merge


【解决方案1】:

嗯,你的错误是在你的 while 循环之后

while i < len(left) and j < len(right):
  ...

可能(并且很可能会)i &lt; len(left)j &lt; len(right),因此您需要在答案中附加适当部分的后缀。

很容易做到
result += left[i:]
result += right[j:]

说明:

想象一下合并过程:开始时 i 和 j 在 0 处,并且在每一步都将其中一个向前移动。你什么时候停下来?当其中一个到达终点时。假设我已经走到了尽头。因此,您将整个左侧部分添加到结果中,但在 j 和 len(right) 之间的右侧仍有一些元素,因此您也必须将它们添加到答案中。

离线

你正在实现归并排序,所以请

left = merge_sort( left )
right = merge_sort( right )

而不是

left.sort()
right.sort()

注意:您必须在合并函数开始时将以下检查添加到您的代码中以避免无限递归:

if len( vect ) == 1:
   return vect

您也可以在 print_list 函数中使用

print vect

至少

for x in vect
print x

【讨论】:

  • @user1392136:是的,所以它会在 i >= len(left) 或 j >= len(right) 时中断。其他索引可能仍然较少。
  • 所以答案是我需要 OR 而不是 AND。如果我尝试使用 OR,我会收到超出范围的索引...
  • @user1392136:不,答案是你需要AND,你需要在while后面加上left或right的未查看部分
  • 啊..我明白了..谢谢。还有一件事,如果我调用 left = merge_sort(left) 我收到的最大递归深度超出了。
  • @user1392136:我已经对此进行了解释以及您之前对答案的评论。只需检查数组的大小是否为 1 以在该点停止递归。
【解决方案2】:

只要 left 或 right 用完,while 循环就会退出。这使得未用尽列表中剩余的所有元素都未合并。

将您的代码更改为:

def print_list(vect):
    for i in range(0, len(vect)):
        print(vect[i])

def merge_sort(vect):
    left = []
    right = []

    result = []
    for i in range(0, int(len(vect)/2)):
        left.append(vect[i])
    for i in range(int(len(vect)/2), len(vect)):
        right.append(vect[i])

    left.sort();
    right.sort();
    i = 0
    j = 0

    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1

    if i < len(left):
        result.extend(left[i:])
    else:
        result.extend(right[j:])

    print(len(result))
    return result

vect = [3, 1, 5, 7, 10, 2, 0]

vect = merge_sort(vect)
print vect

如果您使用左右排序方法,我有点困惑为什么您不只是在整个列表中使用它。但我想你有你的理由。 :)

编辑:我把整个代码块放在那里,这样你就可以看到它。当我运行它时,它会打印 [0, 1, 2, 3, 5, 7, 10],这是正确的。

【讨论】:

  • 我不明白为什么我需要在 while 结束时添加这个。但是它不起作用...
  • 我将答案调整为更明确一点。也许它现在对你有用。
  • 我不明白为什么以及我需要扩展什么才能使它工作...你能用文字告诉我一些你对新代码行做了什么吗?
  • extend 方法接受一个列表作为参数。它遍历列表并将每个元素附加到父类列表对象。我在上面所做的是获取每个列表的剩余部分(使用列表切片符号 [i:] 或 [j:] 完成),然后将所有剩余元素添加到结果列表中。
  • 当它不是递归的时候,这可以被认为是真正的合并排序吗?从技术上讲,您对 left.sort() 和 right.sort() 的调用应该回调 MergeSort,我错了吗?
猜你喜欢
  • 1970-01-01
  • 2017-06-30
  • 2021-01-25
  • 2020-10-10
  • 2017-03-28
  • 1970-01-01
  • 2011-02-09
  • 2019-10-11
相关资源
最近更新 更多