I'm trying to implement merge sort in python as following:
def MergeSortTopdown(list_n):
#Base condition to stop recursion
if len(list_n) == 1:
return list_n
else:
mid = int(len(list_n)/2)
first_half = list_n[:mid]
second_half = list_n[mid:]
MergeSortTopdown(first_half)
MergeSortTopdown(second_half)
i = 0
j = 0
n = len(list_n)
for k in range(n):
if j >= len(first_half) and i < len(second_half):
list_n[k] = first_half[i]
i += 1
if i >= len(first_half) and j < len(second_half):
list_n[k] = second_half[j]
j += 1
if i < len(first_half) and j < len(second_half):
if first_half[i] > second_half[j]:
list_n[k] = second_half[j]
j += 1
elif second_half[j] > first_half[i]:
list_n[k] = first_half[i]
i += 1
elif second_half[i] == first_half[j]:
list_n[k] = first_half[i]
if i>j:
i += 1
else:
j += 1
return list_n
it seems reasonable when I tested with already sorted list. However, when I run, this error raises:
MergeSortTopdown([3,4,6,7,1,8,56,112,67])
Traceback (most recent call last):
File "<ipython-input-11-29db640f4fc6>", line 1, in <module>
MergeSortTopdown([3,4,6,7,1,8,56,112,67])
File "C:/Users/Emmanuel Hoang/MergeSortTopDown.py", line 13, in MergeSortTopdown
MergeSortTopdown(second_half)
File "C:/Users/Emmanuel Hoang/MergeSortTopDown.py", line 13, in MergeSortTopdown
MergeSortTopdown(second_half)
File "C:/Users/Emmanuel Hoang/MergeSortTopDown.py", line 19, in MergeSortTopdown
list_n[k] = first_half[i]
IndexError: list index out of range
Can you tell me what's wrong with my code, is there any way that I can improve my code. Thank you in advance
You've tried to reference an element past the end of the list. I added some straightforward print
statements to your code:
for k in range(n):
print("LOOP TOP", k, first_half, second_half, list_n)
if j >= len(first_half) and i < len(second_half):
print("TRACE", list_n, k, "\t", first_half, i)
list_n[k] = first_half[i]
i += 1
Then I shortened the input list to [8,56,112,3,67]
.
Output:
LOOP TOP 0 [8] [56] [8, 56]
LOOP TOP 1 [8] [56] [8, 56]
LOOP TOP 0 [3] [67] [3, 67]
LOOP TOP 1 [3] [67] [3, 67]
LOOP TOP 0 [112] [3, 67] [112, 3, 67]
LOOP TOP 1 [112] [3, 67] [3, 3, 67]
TRACE [3, 3, 67] 1 [112] 0
LOOP TOP 2 [112] [3, 67] [3, 67, 67]
TRACE [3, 67, 67] 2 [112] 1
This is followed by the crash you got. You try to fetch first_half[1]
when there's only an element 0.
ANALYSIS
You have three successive if
statements to check list bounds:
if j >= len(first_half) and i < len(second_half):
if i >= len(first_half) and j < len(second_half):
if i < len(first_half) and j < len(second_half):
You have i
and j
switched in the first check: i
is the first_half
subscript. This change fixes the merge:
if i < len(first_half) and j >= len(second_half):
Suggestions
Part of your problem is that your merge logic is too complex. You have a single value check during the main part of the loop: move the lower of the list heads to the merged list. Do this while both indices are in range.
Then, when one index hits the end of its list, drop out of the loop and add the remaining elements of the other list. Use the extend
method. So ...
while i < len(first_half) and j < len(second_half):
if first_half[i] < second_half[j]:
# move smaller element to list_n;
# increment i or j as needed
k += 1
# One of these will be an empty operation.
list_n.extend(first_half[i:])
list_n.extend(second_half[j:])
IndexError
: The first case that you check for in your 'merge step' of the merge sort -- if you have already merged all elements from the list second_half
-- has the names of your two lists first_half
and second_half
switched around. Instead of this:
if j >= len(first_half) and i < len(second_half):
list_n[k] = first_half[i]
i += 1
you should have this:
if j >= len(second_half) and i < len(first_half):
list_n[k] = first_half[i]
i += 1
This will correctly check for the condition specified above.
The reason why you received an IndexError
is because you were trying to call first_half[i]
and were not correctly confirming that i
was a valid index in the list first_half
before doing so.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.