【问题标题】:Why can't I implement merge sort this way为什么我不能以这种方式实现归并排序
【发布时间】:2017-12-28 07:43:21
【问题描述】:

我了解合并排序的工作原理是分而治之,你不断减半,直到你达到可以在恒定时间内排序的地步,或者列表只是一个元素,然后你合并列表。

def mergesort(l):
    if len(l)<=1:
        return l
    l1 = l[0:len(l)//2+1]
    l2 = l[len(l)//2:]

    l1 = mergesort(l1)
    l2 = mergesort(l2)

    return merge(l1,l2)

我有一个有效的合并实现,我检查它工作正常,但合并排序实现不起作用,它只返回列表的一半元素。

我在互联网上看到合并排序是使用 l & r 和 m = (l + r)/2 实现的。我的实施有什么问题?我也在递归地细分列表并合并。

【问题讨论】:

  • 不知道为什么它只返回一半,但你不需要+1 in [0:len(l)//2+1]。您能否在问题中添加merge 实现?

标签: python algorithm sorting merge mergesort


【解决方案1】:

问题是您代码中的+1,这里:

l1 = l[0:len(l)//2]
l2 = l[len(l)//2:]

用你的代码替换它就可以了

【讨论】:

    【解决方案2】:

    您列出的代码似乎没有进行任何排序。我无法确定,因为您没有列出 merge() 函数的代码,但上述函数唯一能做的就是递归地将列表分成两半。这是合并排序的一个工作实现:

    def mergeSort(L):
    
        # lists with only one value already sorted
        if len(L) > 1:
            # determine halves of list
            mid = len(L) // 2
            left = L[:mid]
            right = L[mid:]
    
            # recursive function calls
            mergeSort(left)
            mergeSort(right)
    
            # keeps track of current index in left half
            i = 0
            # keeps track of current index in right half
            j = 0
            # keeps track of current index in new merged list
            k = 0
    
            while i < len(left) and j < len(right):
                # lower values appended to merged list first
                if left[i] < right[j]:
                    L[k] = left[i]
                    i += 1
                else:
                    L[k] = right[j]
                    j += 1
                k += 1
    
            # catch remaining values in left and right
            while i < len(left):
                L[k] = left[i]
                i += 1
                k += 1
    
            while j < len(right):
                L[k] = right[j]
                j += 1
                k += 1
        return L
    

    您的函数不对原始列表中的值进行比较。此外,当您将列表分成两半时:

    l1 = l[0:len(l)//2 + 1]
    

    “+ 1”是不必要的(实际上会导致错误的解决方案)。您可以简单地使用:

    l1 = l[:len(l)//2]
    

    如果长度是偶数(即 12),它将把 [0:6] 和 [6:12] 分成两半。如果它很奇怪,它仍然会自动正确划分(即长度 = 13 将是 [0:6] 和 [6:13]。我希望这会有所帮助!

    【讨论】:

    • 如果您有任何问题,欢迎私信我!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2019-07-31
    • 2012-01-24
    • 1970-01-01
    • 2018-11-28
    • 2012-03-20
    相关资源
    最近更新 更多