使用合并排序功能时使列表索引超出范围错误

时间:2019-06-30 11:09:00

标签: python algorithm sorting mergesort

我遇到List index out of range错误。 我还使用了 GeeksforGeeks 程序作为参考,但仍然遇到该错误。 如果不在Merge_Sort()函数中使用它而运行它,我不会出错。

def Merge(arr, p, q, r):
    n1 = q-p+1
    n2 = r-q
    L = [0]*n1
    M = [0]*n2

    for i in range(0, n1):
        L[i] = arr[p+i-1]
    for j in range(0, n2):
        M[j] = arr[q+j]
    i = 0
    j = 0
    for k in range(r-1):
        if L[i] <= M[j]:
            arr[k] = L[i]
            i = i+1
        else:
            arr[k] = M[j]
        j = j+1

def Merge_Sort(arr, p, r):
    if p < r:
        q = int((p+r)/2)
        Merge_Sort(arr, p, q)
        Merge_Sort(arr, q+1, r)
        Merge(arr, p, q, r)

ar = [5, 3, 6, 1, 2, 9, 7, 8]
n = len(ar)
Merge_Sort(ar, 1, n)
print(ar)
Error:
 line 14, in Merge
    if L[i]<=M[j]:

IndexError: list index out of range

2 个答案:

答案 0 :(得分:2)

代码不正确:索引值和切片边界以及其他错误也有些混乱:

  • 数组索引从python中的0开始,因此您应该调用Merge_sort(ar, 0, n)

  • 切片长度n1减1,应为n1 = q - p

  • 递归测试应计算切片长度,并且仅对至少包含2个元素的切片进行递归。

  • 合并循环不正确:您应该测试ij是否都在切片内。一种有效的方法是用此测试替换比较:

    if i < n1 and (j == n2 or L[i] <= M[j]):
    
  • 合并循环应将kp迭代到排除的r,而不是从0到排除的r

    < / li>
  • j的增量代码未对齐,应该再缩进一步

考虑包括第一个索引而排除第二个索引要容易得多。网上有太多使用各种语言的教程都坚持使用其他约定,这总是给新手程序员带来困惑。

以下是经过纠正和简化的版本:

def Merge(arr, p, q, r):
    n1 = q - p
    n2 = r - q
    L = arr[p : q]
    M = arr[q : r]
    i = 0
    j = 0
    for k in range(p, r):
        if i < n1 and (j == n2 or L[i] <= M[j]):
            arr[k] = L[i]
            i = i + 1
        else:
            arr[k] = M[j]
            j = j + 1

def Merge_Sort(arr, p, r):
    if r - p >= 2:
        q = (p + r) // 2
        Merge_Sort(arr, p, q)
        Merge_Sort(arr, q, r)
        Merge(arr, p, q, r)

ar = [5, 3, 6, 1, 2, 9, 7, 8]
Merge_Sort(ar, 0, len(ar))
print(ar)

请注意,如果确保左切片始终至少与右切片一样大,则可以使用单个临时数组进一步简化MergeSort函数:

def Merge(arr, p, q, r):
    tmp = arr[p : q]
    i = 0
    n = q - p
    while i < n:
        if q == r or tmp[i] <= arr[q]:
            arr[p] = tmp[i]
            i += 1
            p += 1
        else:
            arr[p] = arr[q]
            q += 1
            p += 1

def Merge_Sort(arr, p, r):
    if r - p >= 2:
        q = (p + r + 1) // 2
        Merge_Sort(arr, p, q)
        Merge_Sort(arr, q, r)
        Merge(arr, p, q, r)

ar = [5, 3, 6, 1, 2, 9, 7, 8]
Merge_Sort(ar, 0, len(ar))
print(ar)

答案 1 :(得分:1)

您的代码不同于GeeksforGeeks代码。我更正了merge函数以匹配它们。您需要三个循环:

  1. LM中取出较小的前几个元素,直到LM为空
  2. 追加L中剩余的元素(如果有)
  3. 追加M中剩余的元素(如果有)

您还需要一个变量来跟踪arr中的当前索引(在这种情况下为k)。

GeeksforGeeks代码:https://www.geeksforgeeks.org/merge-sort/

更正的python代码:

def Merge(arr, p, q, r):
    n1 = q-p+1
    n2 = r-q
    L = [0]*n1
    M = [0]*n2

    for i in range(0,n1):
        L[i] = arr[p+i]
    for j in range(0, n2):
        M[j] = arr[q+1+j]
    i = 0
    j = 0
    # result index
    k = p

    # take smallest element until either L or M are empty
    while i < n1 and j < n2:
        if L[i]<=M[j]:
            arr[k] = L[i]
            i = i+1
        else:
            arr[k] = M[j]
            j = j+1
        k = k+1

    # write remaining elements from L
    while i < n1:
        arr[k] = L[i]
        i = i+1
        k = k+1

    # write remaining elements from M
    while j < n2:
        arr[k] = M[j]
        j = j+1
        k = k+1

def Merge_Sort(arr, p, r):
    if p < r:
        q = int((p+r)/2)
        Merge_Sort(arr, p, q)
        Merge_Sort(arr, q+1,r)
        Merge(arr, p, q, r)
ar = [5,3,6,1,2,9,7,8]
n = len(ar)
Merge_Sort(ar,0,n-1)
print(ar)

如果只想使用一个循环,则可以将上述所有内容组合在一起(尽管不易读):

def Merge(arr, p, q, r):
    n1 = q-p+1
    n2 = r-q
    L = [0]*n1
    M = [0]*n2

    for i in range(0,n1):
        L[i] = arr[p+i]
    for j in range(0, n2):
        M[j] = arr[q+1+j]
    i = 0
    j = 0

    for k in range(n1+n2):
        if (i < n1 and j < n2 and L[i]<=M[j]) or j >= n2:
            arr[p+k] = L[i]
            i = i+1
        else:
            arr[p+k] = M[j]
            j = j+1

def Merge_Sort(arr, p ,r):
    if p < r:
        q = int((p+r)/2)
        Merge_Sort(arr, p, q)
        Merge_Sort(arr, q+1,r)
        Merge(arr, p, q, r)
ar = [5,3,6,1,2,9,7,8,]
n = len(ar)
Merge_Sort(ar,0,n-1)
print(ar)