繁体   English   中英

实现归并排序算法

[英]Implementing Merge Sort algorithm

def merge(arr,l,m,h):
    lis = []
    l1 = arr[l:m]
    l2 = arr[m+1:h]
    while((len(l1) and len(l2)) is not 0):
        if l1[0]<=l2[0]:
            x = l1.pop(0)
        else:
        x = l2.pop(0)
        lis.append(x)
    return lis

def merge_sort(arr,l,h): generating them
    if l<h:
        mid  = (l+h)//2
        merge_sort(arr,l,mid)
        merge_sort(arr,mid+1,h)
        arr = merge(arr,l,mid,h)
    return arr

arr = [9,3,7,5,6,4,8,2]
print(merge_sort(arr,0,7))

谁能告诉我我的方法哪里出错了? 我只得到 [6,4,8] 作为答案。 我试图理解算法并以自己的方式实现逻辑。 请帮忙。

几个问题:

  • 当您认为h是子列表的最后一个索引时,请意识到在对列表进行切片时,第二个索引是预期范围之后的索引。 所以改变这个:

    错误的 正确的
    l1 = arr[l:m] l1 = arr[l:m+1]
    l2 = arr[m+1:h] l2 = arr[m+1:h+1]
  • 由于merge返回列表的结果,因此不应将其分配给arr arr应该是总列表,所以你应该只替换它的一部分:

     arr[l:h+1] = merge(arr,l,mid,h)
  • 由于while循环要求两个列表都不为空,因此您仍应考虑在循环之后其中一个列表仍不为空的情况:应将其元素添加到合并结果中。 所以将return语句替换为:

     return lis + l1 + l2
  • 不建议将整数与isis not进行比较,您在while条件下会这样做。 事实上,这个条件可以简化为:

     while l1 and l2:

通过这些更改(和正确的缩进),它将起作用。

补充说明:

这种实现效率不高。 pop(0)的时间复杂度为 O(n)。 使用您在循环期间更新的索引,而不是真正从列表中提取值。

hm成为它们关闭的范围之后的索引,而不是它们是它们关闭的范围内的最后一个元素的索引,这更像是 Pythonic。 所以如果你 go 那样,那么上面的一些问题将得到不同的解决。

更正的实施

这是使用上述所有注释改编的代码:

def merge(arr, l, m, h):
    lis = []
    i = l
    j = m
    while i < m and j < h:
        if arr[i] <= arr[j]:
            x = arr[i]
            i += 1
        else:
            x = arr[j]
            j += 1
        lis.append(x)
    return lis + arr[i:m] + arr[j:h]

def merge_sort(arr, l, h):
    if l < h - 1:
        mid  = (l + h) // 2
        merge_sort(arr, l, mid)
        merge_sort(arr, mid, h)
        arr[l:h] = merge(arr, l, mid, h)
    return arr


arr = [9, 3, 7, 5, 6, 4, 8, 2]
print(merge_sort(arr,0,len(arr)))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM