首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mergesort递推

Mergesort递推
EN

Code Review用户
提问于 2015-07-25 16:35:15
回答 2查看 108关注 0票数 2

有人能看一下下面的递归合并排序,并告诉我是否有任何改进吗?我主要感兴趣的要么是提高代码速度,要么是缩短代码。

代码语言:javascript
复制
def mergesort(alist):
    if len(alist) > 1:
        mid = len(alist)/2
        left = alist[:mid]
        right = alist[mid:]

        mergesort(left)
        mergesort(right)

        i = 0
        j = 0
        k = 0

        while i < len(left) and j < len(right):
            if left[i] > right[j]:
                alist[k] = right[j]
                j = j + 1

            elif left[i] < right[j]:
                alist[k] = left[i]
                i = i + 1

            k = k + 1

        while i < len(left):
            alist[k] = left[i]
            i = i + 1
            k = k + 1

        while j < len(right):
            alist[k] = right[j]
            j = j + 1
            k = k + 1


A = [4, 3, 1, 2, 6, 8, 10]

mergesort(A)
print(A)
EN

回答 2

Code Review用户

发布于 2015-07-25 18:05:48

将一份清单切成一份副本,例如:

代码语言:javascript
复制
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b = a[:5]
>>> b
[0, 1, 2, 3, 4]
>>> b[2] = 0
>>> b
[0, 1, 0, 3, 4]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

因此,每次递归调用都是在传递列表之前创建一半的列表副本,这不是最好的时间利用。我认为传递整个列表是一种更好的方法,它只是传递对整个列表的引用,不涉及副本,并且有几个索引标记了您想要处理的范围:

代码语言:javascript
复制
def mergesort(alist, lo=0, hi=None):
    if hi is None:
        hi = len(alist)
    if hi - lo <= 1:
        return
    mid = lo + (hi - lo) // 2  # mid = (lo + hi) // 2 can overflow
    mergesort(alist, lo=lo, hi=mid)
    mergesort(alist, lo=mid, hi=hi)
    # Copy out the left side, which may be overwritten by the merge
    temp = alist[lo:mid]
    read_left = 0  # index into temp, copy of left subarray
    read_right = mid  # index into alist's right subarray
    write = lo  # index into alist
    while read_left < len(temp) and read_right < hi:
        if alist[read_right] < temp[read_left]:
            alist[write] = alist[read_right]
            read_right += 1
        else:
            alist[write] = temp[read_left]
            read_left += 1
        write += 1
    # Copy any unprocessed items in temp back to alist
    alist[write:write+len(temp)-read_left] = temp[read_left:]
    # Any unprocessed items in right subarray are already in place!
    # Nothing returned: the list gets sorted in-place
票数 3
EN

Code Review用户

发布于 2015-07-25 17:00:21

为什么不改变

代码语言:javascript
复制
while i < len(left) and j < len(right):
    if left[i] > right[j]:
        alist[k] = right[j]
        j = j + 1

    elif left[i] < right[j]:
        alist[k] = left[i]
        i = i + 1

    k = k + 1

代码语言:javascript
复制
while i < len(left) and j < len(right):
    if left[i] > right[j]:
        alist[k] = right[j]
        j = j + 1

    else:  // !! Note the 'else'
        alist[k] = left[i]
        i = i + 1

    k = k + 1

这样,您就不会“跳过”(可能)相同的元素。

编辑:更糟糕的是,如果在输入数组中添加任何重复元素,则实现将永远循环。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/98052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档