Skip to content

Commit 3e2f139

Browse files
committed
Add insertion sort and mergesort
0 parents  commit 3e2f139

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

sorting_algorithms.py

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
from typing import List
2+
3+
4+
def top_down_mergesort(arr: List[float]) -> List[float]:
5+
# Cutoff chosen based on runtime improvement consistency after various tests.
6+
insertion_sort_cutoff = 15
7+
8+
def sort(lo: int, hi: int):
9+
if lo >= hi:
10+
return
11+
12+
# Optimize by running an insertion sort on small arrays.
13+
if ((hi - lo) + 1) <= insertion_sort_cutoff:
14+
return _subsequence_insertion_sort(arr, lo, hi)
15+
16+
# Sort the left half and the right half of the array.
17+
mid = lo + (hi - lo) // 2
18+
sort(lo, mid)
19+
sort(mid + 1, hi)
20+
21+
# The array is already sorted.
22+
if arr[mid] <= arr[mid + 1]:
23+
return
24+
25+
# Copy the values to be merged in a temp array. Alternatively,
26+
# iterate over the original array and populate the temp array
27+
# with the sorted values, and copy the temp array back in sequence.
28+
temp_arr = arr[lo:hi + 1]
29+
30+
# Initialize the pointers needed to modify the original array.
31+
left_half_ptr = lo
32+
right_half_ptr = mid + 1
33+
original_arr_index = lo
34+
35+
# If both halves of the array have values left, compare their values
36+
# and merge back into the correct place in the original array.
37+
while left_half_ptr <= mid and right_half_ptr <= hi:
38+
if temp_arr[left_half_ptr - lo] <= temp_arr[right_half_ptr - lo]:
39+
arr[original_arr_index] = temp_arr[left_half_ptr - lo]
40+
left_half_ptr += 1
41+
else:
42+
arr[original_arr_index] = temp_arr[right_half_ptr - lo]
43+
right_half_ptr += 1
44+
45+
original_arr_index += 1
46+
47+
# One half of the array has run out of values, so just merge the
48+
# remaining values from the left or right half.
49+
while right_half_ptr <= hi:
50+
arr[original_arr_index] = temp_arr[right_half_ptr - lo]
51+
right_half_ptr += 1
52+
original_arr_index += 1
53+
54+
while left_half_ptr <= mid:
55+
arr[original_arr_index] = temp_arr[left_half_ptr - lo]
56+
left_half_ptr += 1
57+
original_arr_index += 1
58+
59+
sort(0, len(arr) - 1)
60+
return arr
61+
62+
63+
def insertion_sort(arr: List[float]) -> List[float]:
64+
for i, curr_num in enumerate(arr):
65+
prev_elements_ptr = i - 1
66+
67+
# Compare the current element with all previously considered elements,
68+
# moving the considered element to the right if the current is smaller.
69+
while prev_elements_ptr >= 0 and curr_num < arr[prev_elements_ptr]:
70+
arr[prev_elements_ptr + 1] = arr[prev_elements_ptr]
71+
prev_elements_ptr -= 1
72+
73+
# Now set the current element to its sorted location.
74+
arr[prev_elements_ptr + 1] = curr_num
75+
76+
return arr
77+
78+
79+
# Insertion sort for any subsequence. Helper for other
80+
# sorting algorithms like mergesort and quicksort.
81+
def _subsequence_insertion_sort(arr: List[float], lo: int, hi: int) -> None:
82+
for i in range((hi - lo) + 1):
83+
normalized_index = i + lo
84+
current_num = arr[normalized_index]
85+
prev_elements_ptr = normalized_index - 1
86+
87+
while prev_elements_ptr >= lo and current_num < arr[prev_elements_ptr]:
88+
arr[prev_elements_ptr + 1] = arr[prev_elements_ptr]
89+
prev_elements_ptr -= 1
90+
91+
arr[prev_elements_ptr + 1] = current_num

0 commit comments

Comments
 (0)