简体   繁体   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))

Can anyone please enlighten where my approach is going wrong?谁能告诉我我的方法哪里出错了? I get only [6,4,8] as the answer.我只得到 [6,4,8] 作为答案。 I'm trying to understand the algo and implement the logic my own way.我试图理解算法并以自己的方式实现逻辑。 Please help.请帮忙。

Several issues:几个问题:

  • As you consider h to be the last index of the sublist, then realise that when slicing a list, the second index is the one following the intended range.当您认为h是子列表的最后一个索引时,请意识到在对列表进行切片时,第二个索引是预期范围之后的索引。 So change this:所以改变这个:

    Wrong错误的 Right正确的
    l1 = arr[l:m] l1 = arr[l:m+1]
    l2 = arr[m+1:h] l2 = arr[m+1:h+1]
  • As merge returns the result for a sub list, you should not assign it to arr .由于merge返回列表的结果,因此不应将其分配给arr arr is supposed to be the total list, so you should only replace a part of it: arr应该是总列表,所以你应该只替换它的一部分:

     arr[l:h+1] = merge(arr,l,mid,h)
  • As the while loop requires that both lists are not empty, you should still consider the case where after the loop one of the lists is still not empty: its elements should be added to the merged result.由于while循环要求两个列表都不为空,因此您仍应考虑在循环之后其中一个列表仍不为空的情况:应将其元素添加到合并结果中。 So replace the return statement to this:所以将return语句替换为:

     return lis + l1 + l2
  • It is not advised to compare integers with is or is not , which you do in the while condition.不建议将整数与isis not进行比较,您在while条件下会这样做。 In fact that condition can be simplified to this:事实上,这个条件可以简化为:

     while l1 and l2:

With these changes (and correct indentation) it will work.通过这些更改(和正确的缩进),它将起作用。

Further remarks:补充说明:

This implementation is not efficient.这种实现效率不高。 pop(0) has a O(n) time complexity. pop(0)的时间复杂度为 O(n)。 Use indexes that you update during the loop, instead of really extracting the values out the lists.使用您在循环期间更新的索引,而不是真正从列表中提取值。

It is more pythonic to let h and m be the indices after the range that they close, instead of them being the indices of the last elements within the range they close.hm成为它们关闭的范围之后的索引,而不是它们是它们关闭的范围内的最后一个元素的索引,这更像是 Pythonic。 So if you go that way, then some of the above points will be resolved differently.所以如果你 go 那样,那么上面的一些问题将得到不同的解决。

Corrected implementation更正的实施

Here is your code adapted using all of the above remarks:这是使用上述所有注释改编的代码:

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