我正在尝试在python中实现合并排序,如下所示:
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
当我用已经排序的列表进行测试时,这似乎是合理的。但是,当我运行时,会出现此错误:
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
您能告诉我我的代码有什么问题吗,有什么方法可以改善我的代码。预先谢谢你
答案 0 :(得分:1)
您已尝试引用列表末尾的元素。我在您的代码中添加了一些简单的print
语句:
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
然后我将输入列表缩短为[8,56,112,3,67]
。
输出:
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
这是您崩溃后的结果。当元素只有0时,您尝试获取first_half[1]
。
分析
您有三个连续的if
语句来检查列表范围:
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):
您在第一张支票中切换了i
和j
:i
是first_half
下标。此更改可修复合并:
if i < len(first_half) and j >= len(second_half):
建议
部分问题是合并逻辑过于复杂。在循环的主要部分中,您需要进行一次值检查:将列表标题的下半部分移到合并列表中。当两个索引都在范围内时执行此操作。
然后,当一个索引到达其列表的末尾时,退出循环并添加另一个列表的其余元素。使用extend
方法。所以...
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:])
答案 1 :(得分:0)
IndexError
:您在合并排序的“合并步骤”中检查的第一种情况(如果您已经合并了列表second_half
中的所有元素)具有两个列表的名称{{1} }和first_half
切换。代替这个:
second_half
您应该有这个:
if j >= len(first_half) and i < len(second_half):
list_n[k] = first_half[i]
i += 1
这将正确检查上述条件。
收到if j >= len(second_half) and i < len(first_half):
list_n[k] = first_half[i]
i += 1
的原因是因为您试图呼叫IndexError
且之前未正确确认first_half[i]
是列表i
中的有效索引这样做。