Skip to content

Commit 9a47781

Browse files
authored
Merge pull request #1 from shubham-x06/shubham-x06-patch-1
Create merge_sort_3_partition.py
2 parents a71618f + 488927b commit 9a47781

1 file changed

Lines changed: 126 additions & 0 deletions

File tree

merge_sort_3_partition.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
"""
2+
Three-way (ternary) merge sort.
3+
4+
Doctests:
5+
python -m doctest -v three_way_merge_sort.py
6+
or
7+
python3 -m doctest -v three_way_merge_sort.py
8+
9+
Manual test:
10+
python three_way_merge_sort.py
11+
"""
12+
13+
from typing import List, Any
14+
15+
16+
def merge_sort(collection: List[Any]) -> List[Any]:
17+
"""
18+
Sorts a list using a three-way merge sort (split into 3 parts).
19+
20+
:param collection: A mutable ordered collection with comparable items.
21+
:return: The same collection ordered in ascending order.
22+
23+
Time Complexity: O(n log_3 n) ≈ O(n log n)
24+
Space Complexity: O(n)
25+
26+
Examples:
27+
>>> merge_sort([0, 5, 3, 2, 2])
28+
[0, 2, 2, 3, 5]
29+
>>> merge_sort([])
30+
[]
31+
>>> merge_sort([-2, -5, -45])
32+
[-45, -5, -2]
33+
>>> merge_sort([9,1,8,2,7,3,6,4,5])
34+
[1, 2, 3, 4, 5, 6, 7, 8, 9]
35+
"""
36+
37+
def merge_three(left: List[Any], middle: List[Any], right: List[Any]) -> List[Any]:
38+
"""
39+
Merge three sorted lists into a single sorted list.
40+
41+
Uses indices for efficiency.
42+
"""
43+
i = j = k = 0
44+
nL, nM, nR = len(left), len(middle), len(right)
45+
result: List[Any] = []
46+
47+
# While all three have elements, pick the smallest of the three
48+
while i < nL and j < nM and k < nR:
49+
if left[i] <= middle[j] and left[i] <= right[k]:
50+
result.append(left[i]); i += 1
51+
elif middle[j] <= left[i] and middle[j] <= right[k]:
52+
result.append(middle[j]); j += 1
53+
else:
54+
result.append(right[k]); k += 1
55+
56+
# Now at least one list is exhausted. Merge remaining two (pairwise)
57+
# Merge left & middle
58+
while i < nL and j < nM:
59+
if left[i] <= middle[j]:
60+
result.append(left[i]); i += 1
61+
else:
62+
result.append(middle[j]); j += 1
63+
64+
# Merge middle & right
65+
while j < nM and k < nR:
66+
if middle[j] <= right[k]:
67+
result.append(middle[j]); j += 1
68+
else:
69+
result.append(right[k]); k += 1
70+
71+
# Merge left & right
72+
while i < nL and k < nR:
73+
if left[i] <= right[k]:
74+
result.append(left[i]); i += 1
75+
else:
76+
result.append(right[k]); k += 1
77+
78+
# Append leftovers (at most one of the three loops below will add many)
79+
while i < nL:
80+
result.append(left[i]); i += 1
81+
while j < nM:
82+
result.append(middle[j]); j += 1
83+
while k < nR:
84+
result.append(right[k]); k += 1
85+
86+
return result
87+
88+
# Base case
89+
n = len(collection)
90+
if n <= 1:
91+
return collection[:]
92+
93+
# Split into three roughly equal parts
94+
third = n // 3
95+
mid1 = third - 1 # last index of first part (not used directly)
96+
# compute split indices for slicing
97+
cut1 = third
98+
cut2 = 2 * third + (1 if n % 3 == 2 else 0) # distribute remainder to the second cut
99+
100+
left = collection[:cut1]
101+
middle = collection[cut1:cut2]
102+
right = collection[cut2:]
103+
104+
# Recursively sort the three parts
105+
sorted_left = merge_sort(left)
106+
sorted_middle = merge_sort(middle)
107+
sorted_right = merge_sort(right)
108+
109+
# Merge three sorted parts and return
110+
return merge_three(sorted_left, sorted_middle, sorted_right)
111+
112+
113+
if __name__ == "__main__":
114+
import doctest
115+
doctest.testmod()
116+
117+
try:
118+
user_input = input("Enter numbers separated by a comma:\n").strip()
119+
if not user_input:
120+
print("[]")
121+
else:
122+
unsorted = [int(item) for item in user_input.split(",")]
123+
sorted_list = merge_sort(unsorted)
124+
print(*sorted_list, sep=",")
125+
except ValueError:
126+
print("Invalid input. Please enter valid integers separated by commas.")

0 commit comments

Comments
 (0)