使用Python自下而上MergeSort

时间:2016-05-21 23:12:45

标签: python mergesort bottom-up

我花了无数个小时试图这样做。有谁可以指出我的错误?

a只是一个列表,tmp是一个大小为len(a)的空列表

z基本上是len(a)

a = [6,5,4,3,2,1] print 'unsorted:',a z = len(a) tmp = range(len(a))

这是我的排序功能:

def sort(a,tmp):
        width=1
        while(width<z):
                p=0
                while(p<z):
                        left =p
                        middle = p+width
                        right = p+2*width
                        merge(a,left,middle,right,tmp)
                        p = p+2*width
                t=0        
                while(t<z):
                    a[t]=tmp[t]
                    t=t+1
                width=width*2
                print '\n'

以及此处的合并功能:

def merge(a,iLeft,iMiddle,iRight,tmp):
        i = iLeft
        j = iMiddle
        k = iLeft
        print iLeft,iMiddle,iRight,'[',i,j,k,']'
        #print i ,j, k,'\n\n'

        while(i<iMiddle or j<iRight):
                if(i<iMiddle and j<iRight):
                        if(a[i]<a[j]):
                                tmp[k]=a[i]
                                i += 1
                                k += 1
                        else:
                                tmp[k]=a[j]
                                j += 1
                                k += 1

                elif (i==iMiddle):
                        tmp[k] = a[j]
                        j += 1
                        k += 1
                elif (j==iRight):
                        tmp[k]= a[i]
                        i += 1
                        k += 1

[此可视化]可能有所帮助。我仍然不知道为什么这样做。

我不知道我哪里出错了?是缩进还是循环?

Output ::
unsorted: [6, 5, 4, 3, 2, 1]
0 1 2 [ 0 1 0 ]
2 3 4 [ 2 3 2 ]
4 5 6 [ 4 5 4 ]


0 2 4 [ 0 2 0 ]
4 6 8 [ 4 6 4 ]
Traceback (most recent call last):
  File "BUmer.py", line 45, in <module>
    sort(a,tmp)
  File "BUmer.py", line 14, in sort
    merge(a,left,middle,right,tmp)
  File "BUmer.py", line 27, in merge
    if(a[i]<a[j]):
IndexError: list index out of range

This visualization可能有所帮助。我仍然不知道为什么会这样。

2 个答案:

答案 0 :(得分:1)

我感到疲惫但很开心。我在PythonTutor上通过令人惊讶的可视化工具偶然发现了答案,并非常注意迭代的数学。

该程序适用于长度=幂为2的数组。 其他所有内容都会从索引异常中提供一个数组。 我应该实现一个try-except块来处理这些事情。

无论如何,现在我知道了。感谢snakes_on_a_keyboard提供有关功能编程的指导。

我之所以没有透露此问题的更多细节,是因为snakes_on_a_keyboard已经提供了更好,更优雅的解决方案。

答案 1 :(得分:0)

虽然这是一个勇敢的努力,但你所做的主要错误是使用嵌套流控制方法 - 人类思维只能处理这么多嵌套的while - 循环。此外,合并功能修改a 到位的事实使得确定正在发生的事情非常困难。即使你有一个能够跟踪所有行动的惊人思维,也可以节省大脑能量来解决问题,而不是控制流量!

通常,您希望尽力保持​​程序平面 - 避免嵌套流量控制。此外,除非您正在进行专门的面向对象编程,否则您应该尝试返回特定值,而不是修改a

这是另一种尝试使事情更加平坦和明确的mergesort方法:

def merge(merged, a, b):

    if a and b:
        return merge(merged + [min(a[0], b[0])],
                     a[1:] if min(a[0], b[0]) == a[0] else a,
                     b[1:] if min(a[0], b[0]) == b[0] and not a[0] == b[0] else b
                     )

    elif a and not b and len(a) > 1:
        return merged + merge([], a[:len(a)/2], a[len(a)/2:])
    elif a and not b:
        return merged + a
    elif b and not a  and len(b) > 1:
        return merged + merge([], b[:len(b)/2], b[len(b)/2:])
    elif b and not a:
        return merged + b
    else:
        return merged

def mergesort(lst):

    if not lst:
        return []
    elif len(lst) == 2:
        return [min(lst), max(lst)]
    elif len(lst) == 1:
        return lst
    else:
        return merge([], mergesort(lst[:len(lst)/2]), mergesort(lst[len(lst)/2:]))

这种保持显式和最小化流控制结构的努力在称为函数式编程的编程风格中很常见。有一本很棒的免费书,你可以在这里访问:

http://www.oreilly.com/programming/free/files/functional-programming-python.pdf

意识到这可能不是您正在寻找的确切答案,但我希望它有所帮助。