I wanted to implement a Timsort in python.
Here's what I've come up with:
from typing import List
RUN = 32
def insertionSort(unsorted: List[int], left: int, right: int) -> None:
""" Sorts the array using insertion sort """
for i in range(left + 1, right + 1):
temp = unsorted[i]
j = i-1
while unsorted[j] > temp and j >= left:
unsorted[j+1] = unsorted[j]
j -= 1
unsorted[j+1] = temp
def merge(unsorted: List[int], left: int, middle: int, right: int) -> None:
""" Merges two sorted arrays """
len1 = middle - left + 1
len2 = right - middle
left_side = unsorted[left : left + len1]
right_side = unsorted[middle + 1 : middle + len2 + 1]
i = j = 0
k = left
while i < len1 and j < len2:
if left_side[i] <= right_side[j]:
unsorted[k] = left_side[i]
i += 1
else:
unsorted[k] = right_side[j]
j += 1
k += 1
while i < len1:
unsorted[k] = left_side[i]
i += 1
k += 1
while j < len2:
unsorted[k] = right_side[j]
j += 1
k += 1
def timSort(unsorted: List[int], length: int) -> None:
"""
Sorts every 'RUN' elements by insertion sort as
insertion sort is faster for smaller array lengths
"""
# Sorts every RUN elements using insertion sort
for i in range(0, length, RUN):
insertionSort(unsorted, i, min(i + 31, length - 1))
size = RUN
# Merges every sorted subarray using Merge Sort
while size < length:
left = 0
while left < length:
mid = min(left + size - 1, length - 1)
right = min(left + 2 * size - 1, length - 1)
merge(unsorted, left, mid, right)
left += size * 2
size *= 2
if __name__ == '__main__':
unsorted = list(map(int, input('Enter space seperated elements: ').split()))
n = len(unsorted)
timSort(unsorted, n)
print('Here\'s the sorted array: ')
print(*unsorted)
I think it looks good, but I want to make it even better.
PS: What would be the optimal length for RUN
?