【问题标题】:Difficulty with merge sort algorithm归并排序算法的难点
【发布时间】:2015-12-09 11:40:05
【问题描述】:

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

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)

【问题讨论】:

  • while list_a: 表示while len(list_a) != 0:。您不会在 while 块内修改您的 list_a,因此这个循环是无休止的,变量 a1 会增长并超出列表长度。

标签: python mergesort


【解决方案1】:

我对您的脚本进行了三处更改以使其正常工作。正如 sshdup while list_a 所指出的那样,由于您没有删除循环内的任何元素,因此将始终评估为 true。因此,我将while list_a: 更改为len(list_a)&gt;a1,将while list_b: 更改为len(list_b)&gt;b1。我还根据pseudo code 在您的merge_sort 方法中添加了return merge(list_a, left, right)。添加return 语句后,merge_sort 中的while 也可以替换为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

【讨论】:

    【解决方案2】:

    要使代码正常工作,您必须进行 2 项调整:

    1. 用 if 语句替换第 4 行中的 while 循环
    2. 稍微修改一下merge()函数中while循环的代码

    工作代码:

    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)) 打印结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-21
      • 2017-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多