Python合并排序+插入排序混合Tim排序

问题描述

我已经编写了用于插入排序和合并排序的代码。现在,我要实现插入排序并将合并排序合并为Tim排序。

我可以看到Tim排序的示例使用开始,中间和结束输入,但是应该可以不加否定地执行此操作?

我想尽可能保持合并和插入排序,因为输入输出与我的其余代码完全吻合。

from random import randint
minrun = 32

def insertion_sort(in_data):
    s_data = list(in_data)
    for i in range(1,len(s_data)):
        key = s_data[i]
        j = i - 1
        while j >= 0 and key < s_data[j]:
            s_data[j + 1] = s_data[j]
            j -= 1
        s_data[j + 1] = key
    return s_data

def merge(a,b):
    c = []
    a_idx,b_idx = 0,0
    while a_idx < len(a) and b_idx < len(b):
        if a[a_idx] < b[b_idx]:
            c.append(a[a_idx])
            a_idx += 1
        else:
            c.append(b[b_idx])
            b_idx += 1
    if a_idx == len(a):
        c.extend(b[b_idx:])
    else:
        c.extend(a[a_idx:])
    return c

def merge_sort(a):
    if len(a) <= 1:
        return a
    left,right = merge_sort(a[:len(a) // 2]),merge_sort(a[len(a) // 2:])
    return merge(left,right)

def tim_sort(in_data):
    n = len(in_data)

    for start in range(0,n,minrun):
        end = min(start + minrun - 1,n - 1)
        in_data = insertion_sort(in_data,start,end)

    curr_size = minrun
    while curr_size < n:
        for start in range(0,curr_size * 2):
            mid = min(n - 1,start + curr_size - 1)
            end = min(n - 1,mid + curr_size)
            in_data = merge_sort(in_data,mid,end)
        curr_size *= 2
    return in_data

def create_array(size=10,max=50):
    from random import randint
    return [randint(0,max) for _ in range(size)]

我找到了Tim排序的这个示例,但是我在如何使其在代码中正常工作方面感到困惑。

解决方法

2020年11月27日

不清楚从何处获得此示例,但肯定不是不是 timsort。如果要实施timsort,首先要做的是阅读并了解 Tim Peters对算法的描述:

https://svn.python.org/projects/python/trunk/Objects/listsort.txt

这是有关音色的权威文件。您可以使用Google找到各种垃圾。我发现唯一值得一读的参考书是:

https://www.infopulse.com/blog/timsort-sorting-algorithm

是轻量级的,但是相当完整,并且在任何方面都没有严重错误。但是,它确实忽略了疾驰的任何考虑,而疾驰是算法中最棘手的部分。

重要的是要意识到python是一种动态语言,因此,由于内部对象的分配,笨拙地实现timsort会产生一些使用大量内存的事情。 Timsort要求:

  • 就地
  • 排序
  • 稳定性
  • 保持不变
  • 疾驰
  • 全面测试

python中就地排序意味着手动为数据列表建立索引。如果使用片,则每次都分配和处置内存。

网络上有三个python实现值得我了解:

1 https://github.com/reingart/pypy/blob/master/rpython/rlib/listsort.py

2 https://gist.github.com/ruminations/89a045dc0ef7edfb92304a0de0752ee0

3 https://github.com/hu-ng/timsort

第一个是pypy主干的一部分,在rpython中实现。它似乎是cpython实现的改编。 rpython是用于静态编译的python的受限子集。

第二个是经过良好测试的实现,该实现有据可查且相当可读。最后一个显然是大学练习,似乎是完整而正确的,但没有经过很好的测试。

您可以在timsort的python实现中找到数十种其他尝试,但是我所看到的全部要么未能满足基本要求,要么显然是错误的。

最后,如果希望有人帮助您修改代码,则至少应链接到该代码,但最好直接提供它,因为mergesort和insort都不难编码。