Skip to content

Commit 41baeb8

Browse files
committed
sorts: support comparable items in merge sort
1 parent 0c4961e commit 41baeb8

1 file changed

Lines changed: 46 additions & 7 deletions

File tree

sorts/merge_sort.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,77 @@
88
For manual testing run:
99
python merge_sort.py
1010
"""
11+
from typing import Protocol, TypeVar
1112

13+
# CHANGED: Added Comparable Protocol.
14+
# WHY: Merge sort is a comparison-based sorting algorithm, so it should
15+
# support any type of item that can be compared using the < operator,
16+
# not only integers.
1217

13-
def merge_sort(collection: list) -> list:
18+
class Comparable(Protocol):
19+
def __lt__(self, other: object, /) -> bool: ...
20+
21+
# CHANGED: Added a TypeVar bounded to Comparable.
22+
# WHY: This preserves the input element type while ensuring that the
23+
# elements support comparison.
24+
25+
26+
T = TypeVar("T", bound=Comparable)
27+
28+
# CHANGED: list[int] -> list[T]
29+
# WHY: Merge sort can sort any comparable items such as ints, strings,
30+
# and floats.
31+
32+
33+
def merge_sort(collection: list[T]) -> list[T]:
1434
"""
1535
Sorts a list using the merge sort algorithm.
1636
17-
:param collection: A mutable ordered collection with comparable items.
18-
:return: The same collection ordered in ascending order.
37+
:param collection: A collection with comparable items.
38+
:return: The collection ordered in ascending order.
1939
2040
Time Complexity: O(n log n)
2141
Space Complexity: O(n)
2242
2343
Examples:
2444
>>> merge_sort([0, 5, 3, 2, 2])
2545
[0, 2, 2, 3, 5]
46+
2647
>>> merge_sort([])
2748
[]
28-
>>> merge_sort([-2, -5, -45])
49+
50+
>>> merge_sort([-2, -45, -5])
2951
[-45, -5, -2]
52+
53+
# CHANGED: Added a string example.
54+
# WHY: Proves merge_sort works with comparable non-integer types.
55+
>>> merge_sort(["c", "a", "b"])
56+
['a', 'b', 'c']
57+
58+
# CHANGED: Added a float example.
59+
# WHY: Further proves the algorithm is not restricted to integers.
60+
>>> merge_sort([2.5, -1.0, 0.0])
61+
[-1.0, 0.0, 2.5]
3062
"""
3163

32-
def merge(left: list, right: list) -> list:
64+
def merge(left: list[T], right: list[T]) -> list[T]:
3365
"""
3466
Merge two sorted lists into a single sorted list.
3567
3668
:param left: Left collection
3769
:param right: Right collection
3870
:return: Merged result
3971
"""
40-
result = []
72+
result: list[T] = []
4173
while left and right:
42-
result.append(left.pop(0) if left[0] <= right[0] else right.pop(0))
74+
# CHANGED: Use only < instead of <=.
75+
# WHY: Comparable guarantees the < operator. Requiring <=
76+
# would unnecessarily require comparable objects to implement
77+
# an additional comparison method.
78+
if right[0] < left[0]:
79+
result.append(right.pop(0))
80+
else:
81+
result.append(left.pop(0))
4382
result.extend(left)
4483
result.extend(right)
4584
return result

0 commit comments

Comments
 (0)