蒂姆排序简介
Tim Peters在2001年推出了Tim sort,作为Python语言的一种稳定的排序算法,它包括插入排序和合并排序,以提高排序的性能,将数组中的元素分成大小为32或64的块(取决于数组大小),称为Run,然后使用插入排序对这些Run进行排序,因为插入排序在数组大小较小时表现良好,并进一步使用合并排序将其合并,因为合并排序在数组中的元素数量为2的幂时表现最佳。 在本专题中,我们将学习Timm Sort。
如何执行Tim Sort?
Tim Sort是最快的排序算法,它使用2种算法在其最佳情况下工作。
Tim Sort的工作原理是:对小的排序块进行合并排序,使其性能快速。因此,在这里,我们的工作是将数组分割成相同大小的不同运行,并使用插入排序对其进行排序。
例如 - [33,45,21,67,89,15,72,234,109] 。
第一部分
在这里,我们将把这个数组分成大小为=3的运行。
3
[33,45,21] [67,89,15] [72,234,109]
现在我们将对这些运行中的每一个进行插入排序。
[33,45,21] -> [33,45,21] ->[33,21,45] [67,89,15] -> [67,89,15] -> [67,15,89] ->[15,67,89] [72,234,109] -> [72,234,109] -> [72,109,234]
结果数组->[33,21,45,15,67,89,72,109,234] 。
**复杂性--**插入式排序需要二进制搜索一个新元素的正确位置+所有元素向右移动。因此,如果数组中的元素数量为n,那么。
二进制搜索的复杂度=log(n),由于它是针对数组中的每个元素进行的,因此比较的数量=nlog(n)
移位次数=1+2+3....n-1元素=(n-1)*n/2=O(n2)
执行插入排序的成本=nlog(n)比较+n2移位,其中操作系统在执行移位和提高性能方面更加优化。
为了获得最佳性能,我们需要将运行规模保持在2的幂级,最小规模为=32,最大规模为64元素。
第二部分
现在,一旦我们用排序后的元素运行,我们将对它们执行合并排序。
执行合并排序需要一个数组的额外空间来存储用于比较的元素,在很多情况下是左右数组的总和,即6个,但在这里我们要采取一个大小=min(leftArray的大小,rightArray的大小)的数组,这样可以减少所需空间。
现在我们将使用下面的算法对前两次运行进行合并排序
[33,21,45, 15, 67,89, 72,109,234]
第1步 - 初始化一个大小为3的新数组Arr2,将第2次运行的元素复制到新数组2中,并将Arr1中的元素向右移动3位。
[0,0,0,33,21,45]Arr2 --> [15,67,89]。
**第2步 -**比较两个数组中的元素并开始填充Array1。
[0,0,0,33,21,45] [15,67,89] -> 自15<33 ->[15,0,0,33,21,45] [15,0,0,33,21,45] [15,67,89] -> 自33<67 ->[15,33,0,33,21,45] [15,33,0,33,21,45] [15,67,89] -> 21<67 ->[15,33,21,33,21,45] [15,33,21,33,21,45] [15,67,89] ->45<67 -> [15,33,21,45,21,45]
第3步--复制数组中其余未被访问的元素
[15,33,21,45,67,89]
由于使用了较少的额外空间,因此它是一种就地排序的算法,在2个具有相同值的元素被比较的情况下,先取索引较低的值,从而使算法更加稳定。
重复以上3个步骤进行下一次运行,Arr1 = [15,33,21,45,67,89,72,109,234] Arr2 = [72,109,234] 。
结果数组=>[15,33,21, 45,67,72,89, 109,234] 。
合并排序的复杂度=Cm.nlog(n-x),x是合并排序中减少的层数,因此我们的目标必须是增加x,C是我们减少到一半的所需空间数。
对运行进行合并的最佳方案
为了以更有效的方式对这些运行进行合并排序,将它们放在堆栈(runs)中,并将被递归地拉出。
[33,21,45] [15,67,89] [72,109,234]
算法
while(runs.length>=2) : If(runs[2].length > runs[0].length + runs[1].length{ If(runs[0].length > runs[1].length){ Merge(runs[0],runs[1]) } else : break; } else : merge(runs[1],min(runs[0],runs[2])
例子
RUNLENGTH = 32 def iSort(myArr, leftIndex, rightIndex): for x in range(leftIndex + 1, rightIndex+1): temp1 = myArr[x] y = x - 1 while myArr[y] > temp1 and y >= leftIndex: myArr[y+1] = myArr[y] y -= 1 myArr[y+1] = temp1 def mergeArray(myarr, lIndex, mid, rIndex): l1, l2 = mid - lIndex + 1, rIndex - mid leftArr, rightArr = [], [] for i in range(0, l1): leftArr.append(myarr[l + i]) for i in range(0, l2): rightArr.append(myarr[mid + 1 + i]) i, j, k = 0, 0, l while i < l1 and j < l2: if leftArr[i] <= rightArr[j]: arr[k] = leftArr[i] i += 1 else: arr[k] = rightArr[j] j += 1 k += 1 while i < l1: myarr[k] = leftArr[i] k += 1 i += 1 while j < l2: myarr[k] = rightArr[j] k += 1 j += 1 def timSorting(myArr, num): for i in range(0, num, RUNLENGTH): iSort(myArr, i, min((i+31), (num-1))) size = RUNLENGTH while size < num: for left in range(0, num, 2*size): mid = left + size - 1 right = min((left + 2*size - 1), (num-1)) mergeArray(myArr, left, mid, right) size = 2*size if __name__ == "__main__": myArr = [33,45, 21,67,89,15, 72, 234, 109] num = len(myArr) print("Array elements before sorting is") for i in range(0, num): print(myArr[i], end = " ") print() timSorting(myArr, num) print() print("Array elements after sorting is") for i in range(0, num): print(myArr[i], end = " ") print()
输出。
结论 - Timm排序
Tim sort是一种对数组元素进行排序的机制,将它们分成32或64大小的运行,然后使用插入排序对它们进行排序,当数组大小较小时,插入排序被认为是最好的,然后使用合并排序将所有运行按排序顺序合并,因为它对大块的排序元素效果最好,带来的复杂度为O(n log n)时间。
推荐文章
这是一个关于Timm Sort的指南。在这里,我们讨论了如何执行Tim Sort以及2种算法在其最佳情况下工作。你也可以看看下面的文章,以了解更多信息