合并排序算法的难度

时间:2015-12-09 11:40:06

标签: python mergesort

我正在努力理解和实现合并排序。我在这个问题上遇到了一堵砖墙,似乎无法获得有效的实施方案。我当前的实现命中了“列表索引超出范围”错误。这是我的代码:

def merge_sort(list_a):
    mid = len(list_a) // 2
    print('Mid is ', mid)
    while len(list_a) > 1:
        left = list_a[:mid]
        print('Left is now ', left)
        right = list_a[mid:]
        print('Right is now ', right)
        merge_sort(left)
        merge_sort(right)
        merge(list_a, left, right)


def merge(comb_list, list_a, list_b):
    print('Starting the merge.')
    a1, b1, c1 = 0, 0, 0
    na, nb, nc = len(list_a), len(list_b), len(comb_list)
    while a1 < na and b1 < nb:
        if list_a[a1] < list_b[b1]:
            print('Adding from A')
            comb_list[c1] = list_a[a1]
            a1 += 1
        else:
            print('Adding from B')
            comb_list[c1] = list_b[b1] 
            b1 += 1

        c1 += 1

    while list_a:
        comb_list[c1] = list_a[a1]
        c1 += 1
        a1 += 1

    while list_b:
        comb_list[c1] = list_b[b1]
        c1 += 1
        b1 += 1

if __name__ == '__main__':
    list_a = [54,26,93,17,77,31,44,55,20]
    merge_sort(list_a)

2 个答案:

答案 0 :(得分:1)

我对您的脚本进行了三次更改以使其正常工作。正如sshdup所指出的那样while list_a将始终评估为true,因为您不会删除循环内的任何元素。因此,我已将while list_a:更改为len(list_a)>a1,将while list_b:更改为len(list_b)>b1。我还根据pseudo codereturn merge(list_a, left, right)方法添加了merge_sort。添加return语句后,while中的merge_sort也可以替换为if语句。我已经在一个随机的整数数组上对它进行了测试,但它似乎正常工作,但是,像往常一样,你应该测试你的边缘情况,以确保它按预期工作。

def merge_sort(list_a):
    mid = len(list_a) // 2
    print('Mid is ', mid)
    if len(list_a) > 1:
        left = list_a[:mid]
        print('Left is now ', left)
        right = list_a[mid:]
        print('Right is now ', right)
        merge_sort(left)
        merge_sort(right)
        return merge(list_a, left, right)


def merge(comb_list, list_a, list_b):
    print('Starting the merge.')
    a1, b1, c1 = 0, 0, 0
    na, nb, nc = len(list_a), len(list_b), len(comb_list)
    while a1 < na and b1 < nb:
        if list_a[a1] < list_b[b1]:
            print('Adding from A')
            comb_list[c1] = list_a[a1]
            a1 += 1
        else:
            print('Adding from B')
            comb_list[c1] = list_b[b1] 
            b1 += 1

        c1 += 1

    while len(list_a)>a1:
        comb_list[c1] = list_a[a1]
        del list_a[a1]
        c1 += 1
        a1 += 1

    while len(list_b)>b1:
        comb_list[c1] = list_b[b1]        
        c1 += 1
        b1 += 1

if __name__ == '__main__':
    list_a = [54,26,93,17,77,31,44,55,20]
    merge_sort(list_a)
    print list_a

答案 1 :(得分:1)

要使代码有效,您必须进行2次调整:

  1. 使用if-statement
  2. 替换第4行中的while循环
  3. 稍微更改merge()函数中while循环的代码
  4. 工作代码:

    def merge_sort(list_a):
        mid = len(list_a) // 2
        print('Mid is ', mid)
        #Use if statement instead
        if len(list_a) > 1:
            left = list_a[:mid]
            print('Left is now ', left)
            right = list_a[mid:]
            print('Right is now ', right)
            merge_sort(left)
            merge_sort(right)
            merge(list_a, left, right)
            #Print the result
            print(list_a)
            #Or return it directly:
            #return list_a
    
    
    def merge(comb_list, list_a, list_b):
        print('Starting the merge.')
        a1, b1, c1 = 0, 0, 0
        na, nb, nc = len(list_a), len(list_b), len(comb_list)
        while a1 < na and b1 < nb:
            if list_a[a1] < list_b[b1]:
                print('Adding from A')
                comb_list[c1] = list_a[a1]
                a1 += 1
            else:
                print('Adding from B')
                comb_list[c1] = list_b[b1] 
                b1 += 1
    
            c1 += 1
        #Change while loop:
        while a1 < na:
            comb_list[c1] = list_a[a1]
            c1 += 1
            a1 += 1
        #Change while loop:
        while b1 < nb:
            comb_list[c1] = list_b[b1]
            c1 += 1
            b1 += 1
    
    if __name__ == '__main__':
        list_a = [54,26,93,17,77,31,44,55,20]
        merge_sort(list_a)
    

    您可能希望直接返回结果,只需添加

    即可
    return list_a
    

    在merge_sort()函数的末尾。使用该方法,您可以使用main方法中的print(merge_sort(list_a))直接打印结果。