From c5d8e9fd783259401816560468fa840412dc66b6 Mon Sep 17 00:00:00 2001 From: Bryan Yue Date: Mon, 5 Jan 2026 00:54:57 -0800 Subject: [PATCH] merge sort --- .gitignore | 3 ++- src/sort/merge_sort.py | 38 +++++++++++++++++++++++++++++++++++++ tst/sort/test_merge_sort.py | 31 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/sort/merge_sort.py create mode 100644 tst/sort/test_merge_sort.py diff --git a/.gitignore b/.gitignore index 77f7f0b..d50d6d7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ venv .vscode .coverage htmlcov -__* \ No newline at end of file +__* +.venv \ No newline at end of file diff --git a/src/sort/merge_sort.py b/src/sort/merge_sort.py new file mode 100644 index 0000000..c8fd447 --- /dev/null +++ b/src/sort/merge_sort.py @@ -0,0 +1,38 @@ +def sort(array): + """Sorts array in-place using merge sort.""" + + def merge_sort(start_idx, end_idx, buffer): + if start_idx >= end_idx: + return + + mid = (start_idx + end_idx) // 2 + merge_sort(start_idx, mid, buffer) + merge_sort(mid + 1, end_idx, buffer) + merge(start_idx, mid, end_idx, buffer) + + def merge(start_idx, mid, end_idx, buffer): + buffer[start_idx : end_idx + 1] = array[start_idx : end_idx + 1] + left = start_idx + right = mid + 1 + current = start_idx + + while left <= mid and right <= end_idx: + if buffer[left] <= buffer[right]: + array[current] = buffer[left] + left += 1 + else: + array[current] = buffer[right] + right += 1 + current += 1 + + while left <= mid: + array[current] = buffer[left] + left += 1 + current += 1 + + # elements from right half already in correct place + + if len(array) <= 1: + return + + merge_sort(0, len(array) - 1, array[:]) diff --git a/tst/sort/test_merge_sort.py b/tst/sort/test_merge_sort.py new file mode 100644 index 0000000..3f2723e --- /dev/null +++ b/tst/sort/test_merge_sort.py @@ -0,0 +1,31 @@ +from src.sort.merge_sort import sort + + +class TestMergeSort: + def test_empty_array(self): + data = [] + sort(data) + assert data == [] + + def test_single_element(self): + data = [42] + sort(data) + assert data == [42] + + def test_sorted_and_reverse_inputs(self): + sorted_array = [1, 2, 3, 4, 5] + reverse_array = list(reversed(sorted_array)) + sort(sorted_array) + sort(reverse_array) + assert sorted_array == [1, 2, 3, 4, 5] + assert reverse_array == [1, 2, 3, 4, 5] + + def test_mixed_values(self): + data = [5, -1, 3, 0, 3, 2, -5] + sort(data) + assert data == [-5, -1, 0, 2, 3, 3, 5] + + def test_duplicates_preserved(self): + data = ["b", "a", "c", "a", "b", "a"] + sort(data) + assert data == ["a", "a", "a", "b", "b", "c"]