python内置的排序算法Timsort浅析

Timsort是一种复杂度高的排序算法,稳定并且效率很高,是python,java等默认使用的一种排序算法
Timsort从某种意义上来说是插入排序与归并排序的结合,
python中,
当一个列表的长度小于等于64时,则默认使用插入排序算法逻辑,对数据进行排序,因为在数据量较小的情况下,插入排序的效率很高,比选择,快排,希尔等都高。
当一个列表长度大于64时,就会结合归并和插入排序算法使用,当然,仅仅是使用他们的一部分而已。
Timsort的核心思想就是利用数组中的一部分有序数列,在Timsort中,数组中的每一段有序数列都被称之为‘run’分区,无论这个run分区是倒序或者是正序,Timsort都会将其调整为正序。
Timsort到底会建立多少run分区呢?这是通过minrun来限制的,通俗来讲,minrun就是run分区的限制条件,当数组长度大于64时,其范围为:[32,64],使得数组长度n/minrun的结果为2的整数次幂或者比2的整数次幂稍微小一点,而n/minrun的结果就是Timsort的初始run的个数。

依次寻找待排序序列中的run,当run的大小小于minrun的值的时候,就利用插入排序向后扩充run,直到与minrun的大小相同

给一段python简单实现的代码:


''''
timSort是python、Java等语言的内置排序函数。timSort将插入排序和归并排序结合,首先将
原始无须列表分割成一个个run,run是将原始无需序列按照对应关系分割而成,一般这里的run
制的是原始序列里面存在的有序序列。任何无序序列可以被分割成有序序列的集合。
说明:这里仅仅实现了timsort的雏形,没有考虑minrun。
'''
 
import time
 
def binary_search(the_array, item, start, end):#二分法插入排序
    if start == end:
        if the_array[start] > item:
            return start
        else:
            return start + 1
    if start > end:
        return start
 
    mid = round((start + end)/ 2)
 
    if the_array[mid] < item:
        return binary_search(the_array, item, mid + 1, end)
 
    elif the_array[mid] > item:
        return binary_search(the_array, item, start, mid - 1)
 
    else:
        return mid
 
def insertion_sort(the_array):
    l = len(the_array)
    for index in range(1, l):
        value = the_array[index]
        pos = binary_search(the_array, value, 0, index - 1)
        the_array = the_array[:pos] + [value] + the_array[pos:index] + the_array[index+1:]
    return the_array
 
def merge(left, right):#归并排序
    if not left:
        return right
    if not right:
        return left
    if left[0] < right[0]:
        return [left[0]] + merge(left[1:], right)
    return [right[0]] + merge(left, right[1:])
 
def timSort(the_array):
    runs, sorted_runs = [], []
    length = len(the_array)
    new_run = []
 
    for i in range(1, length):#将序列分割成多个有序的run
        if i == length - 1:
            new_run.append(the_array[i])
            runs.append(new_run)
            break
        if the_array[i] < the_array[i-1]:
            if not new_run:
                runs.append([the_array[i-1]])
                new_run.append(the_array[i])
            else:
                runs.append(new_run)
                new_run = []
        else:
            new_run.append(the_array[i])
 
    for item in runs:
        sorted_runs.append(insertion_sort(item))
 
    sorted_array = []
    for run in sorted_runs:
        sorted_array = merge(sorted_array, run)
 
    print(sorted_array)
 
arr = [45,2.1,3,67,21,90,20,13,45,23,12,34,56,78,90,0,1,2,3,1,2,9,7,8,4,6]
t0 = time.perf_counter()
timSort(arr)
t1 = time.perf_counter()
print('共%.5f秒' %(t1-t0))

你可能感兴趣的:(python,内置排序,Timsort)