除了冒泡排序,你知道Python内建的排序算法吗?

  • 时间:
  • 浏览:2
  • 来源:彩神3D_神彩3D官方



假如有一天:

if not right:

下面的源代码基于我和 Nanda Javarma 的工作。源代码从不全版,全版都是的是这类于于 Python 的官方 sort() 源代码。这就说 我我实现的俩个 冗杂的 Timsort,能都都都上能 对 Timsort 有个整体把握。此外,Python 中的内置 Timsort 算法是在 C 中正式实现的,假如有一天能获得更好的性能。

new_run = [the_array[0]]

# Brandon Skerritt

break

简而言之,Timsort 做了两件非常好的事情:

通常,将不同长度的相邻 run 归并在同时是这么的。更困难的是还时要要保持稳定。为了处理你这类于于间题图片,Timsort 设置了临时内存。它将俩个 run 中较小的(同时调用 runA 和 runB)放上去你这类于于临时内存中。

runs.append([the_array[i]])

"""Takes two sorted lists and returns a single sorted list by comparing the

sorted_array = []

代码

"""

if not left:

假如有一天 B[0] 的位置非常接近 A 的前端(反之亦然),都都都上能 都都都上能 你这类于于操作就没必要了。Timsort 也会注意到你这类于于点,并通过增加连续获得 A 或 B 的数量提高进入飞奔模式的门槛。假如有一天飞奔模式合理,Timsort 使它更容易重新进入该模式。

# for every item in runs, append it using insertion sort

return start

pos = binary_search(the_array, value, 0, index - 1)

if not new_run:

l = len(the_array)

俩个 好的折衷方案是在堆栈项上维护俩个 不变量,其中 A、B 和 C 是最右边俩个 还未归并片段的长度。

return start + 1



new_run.append(the_array[i])

Insertion sort that timsort uses if the array size is small or if

该算法选着 minrun 的范围为 32 ~ 64。当除以 minrun 时,使原始数组的长度等于或略小于 2 的倍数。

归并



假如有一天 Timsort 将进入飞奔模式。Timsort 全版都是检查 A[0] 和 B[0],就说 我二分法搜索 B[0] 在 A[0] 中的合理位置。原先,Timsort 能都都都上能 将 A 的整个次要移动到合适的位置。假如有一天,Timsort 在 B 中搜索 A[0] 的适当位置。假如有一天,Timsort 将立即移动整个 B 到合适的位置。

当归从不同的 run 时,Timsort 试图平衡俩个 相互矛盾的需求。一方面,让.我希望尽假如有一天地延迟归并,以便利用完后 假如有一天再次出现的模式。但让.我更希望尽快归并,以利用刚才发现的在内存层级中仍然排名很高的 run。让.我就说 我能「过分」延迟合并,假如有一天它记住未合并的运行时要消耗内存,而堆栈的大小是固定的。

Peters 设计 Timsort 是为了利用多量占据 于现实数据集中的有序元素,你这类于于有序元素被称为「natural runs」。总而言之,Timsort 会先遍历所有数据并找到数据中假如有一天排好序的分区,且每俩个 分区能都都都上能 称为俩个 run,最后再按规则将你这类于于 run 归并为俩个 。

当 Timsort 归并 A 和 B 时,它注意到俩个 run 假如有一天连续多次「获胜」。假如有一天 run A 的数值全版小于 run B,都都都上能 都都都上能 run A 会回到原始位置。归并这类于于个 run 会耗费巨大工作量,假如有一天还不要再取得任何效果。

sorted_runs.append(insertion_sort(item))

图源:http://bigocheatsheet.com/

假如有一天 run 的长度小于 minrun,则计算 minrun 减去 run 的长度。让.我能都都都上能 将 run 之外的新元素(minrun - run 个)放上去 run 的上边,并执行插入排序来创建新的 run,你这类于于新的 run 长度和 minrun 相同。

length = len(the_array)

return binary_search(the_array, item, mid + 1, end)

new_run.append(the_array[i])

A > B + C

def merge(left, right):

return start

# for every i in the range of 1 to length of array

value = the_array[index]

想象一堆盘子。你都都都上能 都都都上能 从底部取盘子,时要从顶部取,堆栈也是都都都上能 都都都上能 。

具有预设的内部管理特性的数组具有良好的性能

"""

为了得到折衷方案,Timsort 追踪堆栈上最近的俩个 项,并为你这类于于堆栈项创建了俩个 时要保持为 True 的规则:

if start == end:

假如有一天排序的数组中元素少于 64 个,都都都上能 都都都上能 Timsort 将执行插入排序。插入排序是对小型列表最有效的简单排序,它在大型列表中速度迅速,假如有一天在小型列表中速度调快。插入排序的思路如下:

new_run = []

# https://skerritt.tech

print(sorted_array)

elements one at a time.

if start > end:

火山岩石石有序的区块:run

return [right[0]] + merge(left, right[1:])

else:

if the_array[start] > item:

假如有一天他想掌握 Timsort 的工作最好的依据并对其有所了解,我强烈建议你尝试被委托人实现它!

else:

Timsort 实际上在 Python 中假如有一天内建了,一些这段代码只充当概念解释。要使用 Timsort,只需在 Python 中写:

数组中元素少于 64 个

runs, sorted_runs = [], []

其中 A、B 和 C 是堆栈中最近的俩个 项。

the size of the "run" is small

假如有一天 minrun 是 63,而 run 的长度是 33,都都都上能 不都都都上能 都都都上能 获取 63 - 33 = 30 个新元素。假如有一天将这 30 个新元素放上去 run 的末尾并作为新的元素,一些 run 的第 34 个元素 run[33] 有 30 个子元素。最后只时要对上边 30 个元素执行俩个 插入排序就能创建俩个 长度为 63 的新 run。

return binary_search(the_array, item, start, mid - 1)

B > C

return left

if i == length - 1:

# if the i'th element of the array is less than the one before it

Timsort 现在时要执行归并排序来合并 run,时要确保在归并排序的同时保持稳定和平衡。为了保持稳定,俩个 等值的元素不应该交换,这不仅保持了它们在列表中的原始位置,假如有一天使算法调快。

假如有一天都都都上能 都都都上能 递减,则如下图所示:

for run in sorted_runs:

Timsort 是有三种对真实数据非常有效的排序算法。Tim Peters 在 301 年为 Python 编程语言创造了 Timsort。Timsort 首先分析它要排序的列表,假如有一天基于该分析选着合理方案。

 ●  通过在正确的位置插入元素来建立排序列表

下面的跟踪表说明了插入排序如何对列表 [34, 10, 64, 51, 32, 21] 进行排序的:

return mid

runs.append(new_run)

if left[0] < right[0]:

def insertion_sort(the_array):



new_run.append(the_array[i])



else:

Timsort 的排序时间与 Mergesort 相近,快于一些大多数排序算法。Timsort 实际上借鉴了插入排序和归并排序的最好的依据,后文将全版介绍它的具体过程。

return [left[0]] + merge(left[1:], right)

在你这类于于次要完成完后 ,现在应该在俩个 列表含有一系列已排序的 run。

在此完后 ,为了实现稳定的排序,时要将列表中的项压缩为整数,并将其排序为元组数组。

当 Timsort 搜索到 runs 时,它们会被加带到堆栈中。俩个 简单的堆栈是原先的:

def binary_search(the_array, item, start, end):

"""

for i in range(1, length):

都都都都上能 保持稳定的排序

def timsort(the_array):

Timsort 的原始源代码:https://github.com/python/cpython/blob/master/Objects/listobject.c。

minrun 的大小是根据数组大小选着的。Timsort 算法选着它是为了使随机数组中的大次要 run 变成 minrun。当 run N 的长度等于或略小于 2 的倍数时,归并 2 个数组更加高效。Timsort 选着 minrun 是为了确保 minrun 等于或稍微小于 2 的倍数。

# else if its equal to or more than

Timsort 检查 B[0](值为 5),并使用二分法搜索查找其 A 中的正确位置。

现在 B[0] 在 A 列表的上边,Timsort 检查 B 的正确位置是有无 A[0](即 1),一些让.我要看 1 的位置。你这类于于数在 B 的前部,现在让.我知道 B 在 A 的上边,A 在 B 的前边。

runs.append(new_run)

GALLOPING(飞奔模式)

# for every run in sorted_runs, merge them

用 Tim Peters 被委托人的话来说:

在你这类于于示例中,让.我将从左向右完后 刚结束了排序,其中黑体数字表示新的已排序子数组。在原数组每俩个 元素的排序中,它会从右到左对比已排序子数组,并插入适当的位置。用动图来说明插入排序:

原文发布时间为:2018-11-26

elif the_array[mid] > item:

else:

# if new_run is set to None (NULL)

if the_array[i] < the_array[i-1]:

sorted_array = merge(sorted_array, run)

本文来自云栖社区相互企业合作伙伴“CDA 数据分析师”,了解相关信息能都都都上能 关注“CDA 数据分析师”。

the_array = the_array[:pos] + [value] + the_array[pos:index] + the_array[index+1:]

# based off of this code https://gist.github.com/nandajavarma/a3a6b62f34e74ec4c31674934327bbd3

return right

mid = round((start + end)/ 2)

if the_array[mid] < item:

Timsort 自发明权权以来,就成为 Python、Java 、Android 平台和 GNU Octave 的默认排序算法。

return the_array

for index in range(1, l):



假如有一天列表大于 64 个元素,则 Timsort 算法首先遍历列表,查找「严格」升序或降序的次要(Run)。假如有一天俩个 次要递减,Timsort 将逆转你这类于于次要。假如有一天,假如有一天 run 递减,则如下图所示(run 用粗体表示):

for item in runs:

[1, 2, 3, 4, 5, 6]

通常情况报告下,数据会有一些预设的内部管理特性。Timsort 假设,假如有一天 run A 中的值大多低于 run B 的值,都都都上能 都都都上能 A 的值假如有一天就会小于 B。

timsort([2, 3, 1, 5, 6, 7])



# if i is at the end of the list