Reputation: 85
I am trying to make a recursive merge sort function in python, however, my code would not work. It first splits the code into 1 cell arrays then merges and sorts them together. However, on the second level of the merge, the function reverts back to the arrays that have not been sorted. I was wondering how I can adapt my code for my sorting to work.
def merge(list1, list2):
count1 = count2 = 0
final = []
while count1 < len(list1) and count2 < len(list1):
if list1[count1] <= list2[count2]:
final.append(list1[count1])
count1 += 1
else:
final.append(list2[count2])
count2 += 1
if count1 == len(list1):
for i in range(count2, len(list2)):
final.append(list2[i])
else:
for i in range(count1, len(list1)):
final.append(list1[i])
return final
def merge_sort(nums):
if len(nums) > 1:
list1 = nums[:len(nums) // 2]
list2 = nums[len(nums) // 2:]
merge_sort(list1)
merge_sort(list2)
print(list1,"List1")
print(list2,"list2")
print(merge(list1,list2),"merge")
return merge(list1, list2)
numbers = [2, 1, 3, 4, 6, 5, 8, 7]
print(merge_sort(numbers))
When I entered in [2, 1, 3, 4, 6, 5, 8, 7]
, it is separated into multiple cells. Then it is merged and sorted, [1,2]
, [3,4]
, [5,6]
, [7,8]
. The next merge, however, reverts the sorting. [2,1] + [3,4] = [2,1,3,4]
, [6,5] + [8,7] = [6,5,8,7]
. It returns [2, 1, 3, 4, 6, 5, 8, 7]
at the end.
Upvotes: 5
Views: 112
Reputation: 144770
You do not store the lists returned from the resursive calls, hence the merge phase operates on the original arrays, and fails.
Here is a corrected version:
def merge(list1, list2):
count1 = count2 = 0
final = []
while count1 < len(list1) and count2 < len(list2):
if list1[count1] <= list2[count2]:
final.append(list1[count1])
count1 += 1
else:
final.append(list2[count2])
count2 += 1
if count1 == len(list1):
for i in range(count2, len(list2)):
final.append(list2[i])
else:
for i in range(count1, len(list1)):
final.append(list1[i])
return final
def merge_sort(nums):
if len(nums) > 1:
list1 = merge_sort(nums[:len(nums) // 2])
list2 = merge_sort(nums[len(nums) // 2:])
print(list1, "List1")
print(list2, "list2")
merged = merge(list1, list2)
print(merged, "merge")
return merged
else:
return nums
numbers = [2, 1, 3, 4, 6, 5, 8, 7]
print(merge_sort(numbers))
Upvotes: 0
Reputation: 106
Overall the structure is right. But there are just three smaller mistakes in this code.
The first is just a typo of list1 instead of list2. In the merge function, the while loop should have the condition while count1 < len(list1) and count2 < len(list2):
Next in the merge_sort function. list1 and list2 need to be updated while recursively calling merge_sort. Currently list1 and list2 always stay unsorted which is why the values are not moving around. (See updated below)
Finally, you forgot about the base case when len(nums)==1. In this case the list is already sorted because there is only one value. You still need to return that list though otherwise None is returned.
Merge sort should update to:
def merge_sort(nums):
if len(nums) > 1:
list1 = nums[:len(nums) // 2]
list2 = nums[len(nums) // 2:]
#need to update list1 and list2
list1 = merge_sort(list1)
list2 = merge_sort(list2)
print(list1,"List1")
print(list2,"list2")
new_list = merge(list1,list2)
print(new_list,"merge")
return new_list
#need a base condition
else:
return nums
Upvotes: 1
Reputation: 61526
When you make the recursive calls
merge_sort(list1)
merge_sort(list2)
, those calls produce new list objects (when the return
statement is reached on those calls) which are then ignored (because you have done nothing with them). They do not affect the contents of list1
or list2
, as seen by the current call. (Every time merge_sort
is called, list1
and list2
can potentially refer to different values - calling recursively is not different from any other call in this regard.)
Instead of making the merge
call on the unmodified list1
and list2
, you need to use the return values from the recursive calls.
Separately: you are defining your recursive sort to create a new list. Therefore, in the case where len(nums) <= 1
, you still need to return a new list. Otherwise, when the recursion reaches that step, it will return None
implicitly, and you will get an exception when the previous call in the recursion tries to merge
with that non-list value.
Upvotes: 1
Reputation: 8898
The problem is you have these two calls:
merge_sort(list1)
merge_sort(list2)
But you're assuming they're modifying list1
and list2
in place, which is not really the case... Use an assignment to store them back into their original variables:
list1 = merge_sort(list1)
list2 = merge_sort(list2)
You also have a small typo at the first while
statement at the top, where count2
should be compared to the length of list2
while count1 < len(list1) and count2 < len(list2):
Upvotes: 0