Skip to content

Commit de2725f

Browse files
Update mergesort.py (TheAlgorithms#2563)
* Update mergesort.py 1) Updating the merge sort in python as the previous implementation was modifying the input array 2) divided the division part and conquer part of the merge sort algorithm as 2 functions namely mergeSort and merge. 3) function mergeSort divides the function into halves i.e the purpose of the function will be to divide the array 4) function merge will merge 2 halves into a sorted array 5)Added random test cases using shuffle as suggested by @dhruvmanila 6 The time and space complexity of the previous and my version remains the same. i.e (n log(n) time and n log(n) space 7) changed variables as per the python case as required and suggested by @dhruvmanila 8) Updated function names as suggested by @dhurvmanila * Update mergesort.py Added in few more test cases added type hints for the functions and parameters as suggested by @dhruvmanila formatted the code using Auto Pep8 * Update mergesort.py update and added new testcases * Update mergesort.py Added in doc test in merge function * Update mergesort.py fixing pre-commit fails * Update mergesort.py Co-authored-by: Dhruv <[email protected]>
1 parent 44254cf commit de2725f

File tree

1 file changed

+104
-43
lines changed

1 file changed

+104
-43
lines changed

Diff for: divide_and_conquer/mergesort.py

+104-43
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,109 @@
1-
def merge(arr, left, mid, right):
2-
# overall array will divided into 2 array
3-
# left_arr contains the left portion of array from left to mid
4-
# right_arr contains the right portion of array from mid + 1 to right
5-
left_arr = arr[left : mid + 1]
6-
right_arr = arr[mid + 1 : right + 1]
7-
k = left
8-
i = 0
9-
j = 0
10-
while i < len(left_arr) and j < len(right_arr):
11-
# change sign for Descending order
12-
if left_arr[i] < right_arr[j]:
13-
arr[k] = left_arr[i]
14-
i += 1
15-
else:
16-
arr[k] = right_arr[j]
17-
j += 1
18-
k += 1
19-
while i < len(left_arr):
20-
arr[k] = left_arr[i]
21-
i += 1
22-
k += 1
23-
while j < len(right_arr):
24-
arr[k] = right_arr[j]
25-
j += 1
26-
k += 1
27-
return arr
28-
29-
30-
def mergesort(arr, left, right):
1+
from typing import List
2+
3+
4+
def merge(left_half: List, right_half: List) -> List:
5+
"""Helper function for mergesort.
6+
7+
>>> left_half = [-2]
8+
>>> right_half = [-1]
9+
>>> merge(left_half, right_half)
10+
[-2, -1]
11+
12+
>>> left_half = [1,2,3]
13+
>>> right_half = [4,5,6]
14+
>>> merge(left_half, right_half)
15+
[1, 2, 3, 4, 5, 6]
16+
17+
>>> left_half = [-2]
18+
>>> right_half = [-1]
19+
>>> merge(left_half, right_half)
20+
[-2, -1]
21+
22+
>>> left_half = [12, 15]
23+
>>> right_half = [13, 14]
24+
>>> merge(left_half, right_half)
25+
[12, 13, 14, 15]
26+
27+
>>> left_half = []
28+
>>> right_half = []
29+
>>> merge(left_half, right_half)
30+
[]
3131
"""
32-
>>> mergesort([3, 2, 1], 0, 2)
33-
[1, 2, 3]
34-
>>> mergesort([3, 2, 1, 0, 1, 2, 3, 5, 4], 0, 8)
35-
[0, 1, 1, 2, 2, 3, 3, 4, 5]
32+
sorted_array = [None] * (len(right_half) + len(left_half))
33+
34+
pointer1 = 0 # pointer to current index for left Half
35+
pointer2 = 0 # pointer to current index for the right Half
36+
index = 0 # pointer to current index for the sorted array Half
37+
38+
while pointer1 < len(left_half) and pointer2 < len(right_half):
39+
if left_half[pointer1] < right_half[pointer2]:
40+
sorted_array[index] = left_half[pointer1]
41+
pointer1 += 1
42+
index += 1
43+
else:
44+
sorted_array[index] = right_half[pointer2]
45+
pointer2 += 1
46+
index += 1
47+
while pointer1 < len(left_half):
48+
sorted_array[index] = left_half[pointer1]
49+
pointer1 += 1
50+
index += 1
51+
52+
while pointer2 < len(right_half):
53+
sorted_array[index] = right_half[pointer2]
54+
pointer2 += 1
55+
index += 1
56+
57+
return sorted_array
58+
59+
60+
def merge_sort(array: List) -> List:
61+
"""Returns a list of sorted array elements using merge sort.
62+
63+
>>> from random import shuffle
64+
>>> array = [-2, 3, -10, 11, 99, 100000, 100, -200]
65+
>>> shuffle(array)
66+
>>> merge_sort(array)
67+
[-200, -10, -2, 3, 11, 99, 100, 100000]
68+
69+
>>> shuffle(array)
70+
>>> merge_sort(array)
71+
[-200, -10, -2, 3, 11, 99, 100, 100000]
72+
73+
>>> array = [-200]
74+
>>> merge_sort(array)
75+
[-200]
76+
77+
>>> array = [-2, 3, -10, 11, 99, 100000, 100, -200]
78+
>>> shuffle(array)
79+
>>> sorted(array) == merge_sort(array)
80+
True
81+
82+
>>> array = [-2]
83+
>>> merge_sort(array)
84+
[-2]
85+
86+
>>> array = []
87+
>>> merge_sort(array)
88+
[]
89+
90+
>>> array = [10000000, 1, -1111111111, 101111111112, 9000002]
91+
>>> sorted(array) == merge_sort(array)
92+
True
3693
"""
37-
if left < right:
38-
mid = (left + right) // 2
39-
# print("ms1",a,b,m)
40-
mergesort(arr, left, mid)
41-
# print("ms2",a,m+1,e)
42-
mergesort(arr, mid + 1, right)
43-
# print("m",a,b,m,e)
44-
merge(arr, left, mid, right)
45-
return arr
94+
if len(array) <= 1:
95+
return array
96+
# the actual formula to calculate the middle element = left + (right - left) // 2
97+
# this avoids integer overflow in case of large N
98+
middle = 0 + (len(array) - 0) // 2
99+
100+
# Split the array into halves till the array length becomes equal to One
101+
# merge the arrays of single length returned by mergeSort function and
102+
# pass them into the merge arrays function which merges the array
103+
left_half = array[:middle]
104+
right_half = array[middle:]
105+
106+
return merge(merge_sort(left_half), merge_sort(right_half))
46107

47108

48109
if __name__ == "__main__":

0 commit comments

Comments
 (0)