【问题标题】:Python merge sort + insertion sort hybrid Tim sortPython归并排序+插入排序混合添排序
【发布时间】:2021-02-03 09:45:56
【问题描述】:

我已经编写了插入排序和合并排序的代码。现在我想实现我的插入排序和合并排序为 Tim 排序。

我可以看到 Tim 排序的示例使用了开始、中间和结束输入,但应该可以不用 no 来做到这一点?

如果可能的话,我希望我的合并和插入排序保持原样,因为输入输出非常适合我的其余代码。

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, n, curr_size * 2):
            mid = min(n - 1, start + curr_size - 1)
            end = min(n - 1, mid + curr_size)
            in_data = merge_sort(in_data, start, 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 排序的这个例子,但我很纠结如何让它在我的代码中工作。

【问题讨论】:

    标签: python sorting mergesort insertion-sort timsort


    【解决方案1】:

    2020 年 11 月 27 日

    不清楚你从哪里得到这个例子,但肯定是不是 timsort。如果要实现 timsort,首先要做的是阅读并理解 Tim Peters 对算法的描述:

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

    这是关于 timsort 的权威文档。你可以用谷歌找到各种垃圾。我发现的唯一值得一读的参考资料是:

    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

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

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

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

    第二个是经过良好测试的实现,文档齐全且可读性强。最后一个显然是一个大学练习,似乎是完整和正确的,但没有经过很好的测试。

    您可以在 python 实现 timsort 中找到许多其他尝试,但我所看到的要么未能满足基本要求,要么明显不正确。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-03
      • 2019-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 2013-02-25
      • 1970-01-01
      相关资源
      最近更新 更多