简体   繁体   English

在Python中执行合并合并排序时出现错误

[英]Errors arises when implement merge sort in python

I'm trying to implement merge sort in python as following: 我正在尝试在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

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: 我在代码中添加了一些简单的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

Then I shortened the input list to [8,56,112,3,67] . 然后,我将输入列表缩短为[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. 当只有元素0时,您尝试获取first_half[1]

ANALYSIS 分析

You have three successive if statements to check list bounds: 您具有三个连续的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):

You have i and j switched in the first check: i is the first_half subscript. 您在第一个检查中切换了ijifirst_half下标。 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. 使用extend方法。 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:])

To resolve the IndexError : 解决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. 如果你已经合并列表中的所有元素-你在合并排序的你“的合并操作”检查第一种情况second_half -有你的两个列表的名称first_halfsecond_half切换左右。 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. 这将正确检查上面指定的条件。

Why this was happening: 为什么会这样:

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. 之所以收到IndexError是因为您试图调用first_half[i]并且在执行此操作之前未正确确认ifirst_half列表中的有效索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM