MERGESORT永远不会到达第二个数组/列表

时间:2019-04-06 15:15:00

标签: python mergesort

这是CLSR书中我要遵循的算法:

enter image description here

这是我在Python中的代码:

#merge sort

def merge_sort(A, p, q, r):
    n_prime = q - p + 1
    n_second = r - q
    L = [x for x in range(n_prime + 1)]
    R = [y for y in range(n_second + 1)]

    for i in range(n_prime):
        L[i] = A[p + i - 1]

    for j in range(n_second):
        R[j] = A[q + j]

    L[n_prime] = float("inf")
    R[n_second] = float("inf")

    i = 0
    j = 0

    for k in range(p, r):
        if L[i] <= R[i]:
            A[k] = L[i]
            i += 1
        elif A[k] = R[j]:
            j += 1

    return A



A = [2, 4, 5, 7, 8, 6, 9, 1]

print(merge_sort(A, 0, 3, 7))

其余所有代码都可以正常工作。根据VSCode Debugger的介绍,L和R的创建没有任何障碍,但是在最后一个循环中,存在一个问题:它从不枚举j。 elif条件永远不会满足,因此它永远不会到达第二个列表。

我的算法实现有什么问题?我敢打赌这与本书的数组从1开始但python list的索引从0开始有关。为什么他们这样做呢?在翻译算法时,我应该遵循一条一般规则吗?

谢谢。

3 个答案:

答案 0 :(得分:1)

可能应该是elif A [k] == R [j](两个“ =”符号),您写的是一个赋值。

我认为我发现了问题:应该是L [i] <= R [ j ],而不是R [i]。

为我运行的代码:

#merge sort
def merge_sort(A, p, q, r):
    n_prime = q - p + 1
    n_second = r - q
    L = [x for x in range(n_prime + 1)]
    R = [y for y in range(n_second + 1)]
    for i in range(n_prime):
        L[i] = A[p + i - 1]
    for j in range(n_second):
        R[j] = A[q + j]
    L[n_prime] = float("inf")
    R[n_second] = float("inf")
    i = 0
    j = 0
    print("L:", len(L), ", R:", len(R))
    for k in range(p, r):
        if L[i] <= R[j]:
            print("if", i)
            print(L[i])
            print(R[i])
            A[k] = L[i]
            i += 1
        else: 
            print("else", k, j, A[k], R[j])
            A[k] = R[j]
            j += 1
    return A

}

答案 1 :(得分:0)

您写道:

elif A[k] = R[j]:
    j += 1

当算法说:

else:
    A[k] = R[j]
    j += 1

此处的拼写错误将导致“数组索引超出范围”错误:

if L[i] <= R[i]:

您可能是说:

if L[i] <= R[j]:
  

我的算法实现有什么问题?

不完整;您仅实现了合并过程,而没有实现整个mergesort算法。因此,运行具有上述更正的代码将输出部分排序的列表。

答案 2 :(得分:0)

这是我上周第二次看到CLSR版本。我不喜欢使用“前哨值”(无穷大)来避免对索引进行边界检查的想法,因为它不需要太多代码,并且如果A []是整数数组并且已经存在,则将不起作用包括最大值。必须修改代码,因为数组的CLSR索引范围是1到n,而不是0到n-1。

这里是示例代码,该代码在每次移动后进行边界检查,如果到达子运行的末尾,它将追加剩余的子运行的其余部分。同样,输入参数是beg(运行的第一个索引)和结束(1 +运行的最后一个索引),类似于C ++ std :: vector :: begin()和std :: vector :: end(),这是典型的合并排序的用法。

def mergesort(a,beg,end):
    if (end-beg) > 1:
        mid=(beg+end)//2
        mergesort(a,beg,mid)
        mergesort(a,mid,end)
        merge(a,beg,mid,end)
def merge(a,beg,mid,end):
    left = a[beg:mid]
    right = a[mid:end]
    i = 0
    j = 0
    k = beg   
    while True:
        if left[i] <= right[j]:
            a[k] = left[i]
            i += 1
            k += 1
            if(i < len(left)):
                continue
            a[k:end] = right[j:len(right)]
            break
        else:
            a[k] = right[j]
            j += 1
            k += 1
            if(j < len(right)):
                continue
            a[k:end] = left[i:len(left)]
            break
....
mergesort(a,0,len(a))   #call to merge sort to sort a[]

这不是最佳实现。最好一次分配一个工作数组,而不是在每次合并时分配两个工作子数组,并在每次递归级别上交替合并方向(或者如果每次进行自下而上的合并排序,则更好) ),以避免复制数据。