Python/sorts/timsort.py

82 lines
1.7 KiB
Python
Raw Normal View History

2017-10-01 21:13:54 +00:00
def binary_search(lst, item, start, end):
2017-09-28 19:54:15 +00:00
if start == end:
2017-10-01 21:13:54 +00:00
if lst[start] > item:
2017-09-28 19:54:15 +00:00
return start
else:
return start + 1
if start > end:
return start
2017-10-01 21:13:54 +00:00
mid = (start + end) // 2
if lst[mid] < item:
return binary_search(lst, item, mid + 1, end)
elif lst[mid] > item:
return binary_search(lst, item, start, mid - 1)
2017-09-28 19:54:15 +00:00
else:
return mid
2017-10-01 21:13:54 +00:00
def insertion_sort(lst):
length = len(lst)
for index in range(1, length):
value = lst[index]
pos = binary_search(lst, value, 0, index - 1)
lst = lst[:pos] + [value] + lst[pos:index] + lst[index+1:]
return lst
2017-09-28 19:54:15 +00:00
def merge(left, right):
if not left:
return right
2017-10-01 21:13:54 +00:00
2017-09-28 19:54:15 +00:00
if not right:
return left
2017-10-01 21:13:54 +00:00
2017-09-28 19:54:15 +00:00
if left[0] < right[0]:
return [left[0]] + merge(left[1:], right)
2017-10-01 21:13:54 +00:00
2017-09-28 19:54:15 +00:00
return [right[0]] + merge(left, right[1:])
2017-10-01 21:13:54 +00:00
def timsort(lst):
2017-09-28 19:54:15 +00:00
runs, sorted_runs = [], []
2017-10-01 21:13:54 +00:00
length = len(lst)
new_run = [lst[0]]
sorted_array = []
for i in range(1, length):
if i == length - 1:
new_run.append(lst[i])
2017-09-28 19:54:15 +00:00
runs.append(new_run)
break
2017-10-01 21:13:54 +00:00
if lst[i] < lst[i - 1]:
2017-09-28 19:54:15 +00:00
if not new_run:
2017-10-01 21:13:54 +00:00
runs.append([lst[i - 1]])
new_run.append(lst[i])
2017-09-28 19:54:15 +00:00
else:
runs.append(new_run)
new_run = []
else:
2017-10-01 21:13:54 +00:00
new_run.append(lst[i])
for run in runs:
sorted_runs.append(insertion_sort(run))
2017-09-28 19:54:15 +00:00
for run in sorted_runs:
sorted_array = merge(sorted_array, run)
2017-10-01 21:13:54 +00:00
return sorted_array
def main():
lst = [5,9,10,3,-4,5,178,92,46,-18,0,7]
sorted_lst = timsort(lst)
print(sorted_lst)
if __name__ == '__main__':
main()