-
Notifications
You must be signed in to change notification settings - Fork 267
/
timsort.py
86 lines (68 loc) · 2.67 KB
/
timsort.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"""
Implementacao do algoritmo Timsort
Referencia: https://www.geeksforgeeks.org/timsort/
"""
RUN = 32
def insertion_sort(data, left, right):
"""
Use insertion sort to sort the dataay from the left
index to the right index which is of size atmost RUN.
"""
for index in range(left + 1, right + 1):
temp = data[index]
prev_index = index - 1
while prev_index >= left and data[prev_index] > temp:
data[prev_index + 1] = data[prev_index]
prev_index -= 1
data[prev_index + 1] = temp
def merge_sort(data, left, mid, right):
"""Merge sort function responsible for merging the sorted runs."""
# The data is splited in two parts
left_len = mid - left + 1
left_part = [data[left + i] for i in range(0, left_len)]
right_len = right - mid
right_part = [data[mid + 1 + i] for i in range(0, right_len)]
left_index, right_index, data_index = 0, 0, left
# After comparing, we merge those two lists in larger sub list
while left_index < left_len and right_index < right_len:
if left_part[left_index] <= right_part[right_index]:
data[data_index] = left_part[left_index]
left_index += 1
else:
data[data_index] = right_part[right_index]
right_index += 1
data_index += 1
# Copy remaining elements from the left part
while left_index < left_len:
data[data_index] = left_part[left_index]
data_index += 1
left_index += 1
# Copy remaining elements from the right part
while right_index < right_len:
data[data_index] = right_part[right_index]
data_index += 1
right_index += 1
def timsort(data):
"""Iterative Timsort algorithm."""
data_size = len(data)
# Sort individual sub lists of size RUN
for i in range(0, data_size, RUN):
insertion_sort(data, i, min((i + 31), (data_size - 1)))
# Start merging from size RUN.
# It will merge to form size 64, 128, 256 and so on
size = RUN
while size < data_size:
for left in range(0, data_size, 2 * size):
# Find ending point of left sub list
# mid+1 is starting point of right sub dataay
mid = left + size - 1
right = min((left + 2 * size - 1), (data_size - 1))
# Merge sub list data[left.....mid] & data[mid+1....right]
merge_sort(data, left, mid, right)
# After every merge, we increase left by 2 * size
size = 2 * size
if __name__ == "__main__":
data_to_sort = [99, 15, 23, 0, -9, 1, 45, 2, 10, 15]
print("Unsorted data: ", data_to_sort)
timsort(data_to_sort)
print("Sorted data: ", data_to_sort)