Mergesort代码挂起

时间:2018-05-09 06:02:55

标签: python mergesort

我正在尝试实施mergesort。我有一个工作合并子函数,它适用于排序列表,只需要妥善管理所有列表的合并。

def mergesort(alist):
    alist = [[i] for i in alist]

    def merge(clist, dlist): #assume inputs are sorted
        merged = []
        while True:
            if len(clist) == 0:
                return merged + dlist
            elif len(dlist) == 0:
                return merged + clist
            elif clist[0] < dlist[0]:
                merged.append(clist[0])
                del clist[0]
            elif clist[0] > dlist[0]:
                merged.append(dlist[0])
                del dlist[0]            
        return merged

    while True:
        if len(alist) % 2 == 0 and len(alist) > 2:
            alist = [merge(alist[2*i], alist[2 * i + 1]) for i in range(int(len(alist)/2))]
        elif len(alist) == 2:
            print('ayyy')
            alist = merge(alist[0], alist[-1])
            return alist
        elif len(alist) % 2 == 1 and len(alist) > 1:
            tag = alist[-1]
            del alist[-1]
            alist = [merge(alist[2 * i], alist[2 * i + 1]) for i in range(int(len(alist)/2))]
            alist.append(tag)
        else:
            return alist


print(mergesort([10, 5, 8, 16, 258, 11, 1, 20, 489, 10, 5, 3, 12]))

该功能正常工作,直至最后两个列表。它打印出#ayyy&#39;,这意味着它成为第一个elif语句,然后什么都不做。程序没有终止,它只是旋转它的轮子。调试器显示alist的值也未更新。

2 个答案:

答案 0 :(得分:1)

您只有一个小错误,因为您没有处理merge中的相等元素。这是一个小修复:

if len(clist)==0:
    return merged+dlist
elif len(dlist)==0:
    return merged+clist
elif clist[0]<dlist[0]:
    merged.append(clist[0])
    del clist[0]
elif clist[0]>dlist[0]:
    merged.append(dlist[0])
    del dlist[0]
else: # clist[0]==dlist[0]
    merged.append(clist[0])
    merged.append(dlist[0])
    del clist[0]
    del dlist[0]

答案 1 :(得分:0)

我无法抗拒使用迭代器重写merge的诱惑,其方式不会改变参数列表。

def merge(clist, dlist):
    "Merges two sorted lists into one still sorted list"
    if not clist:      # Trivial empty cases
        return dlist
    if not dlist:
        return clist
    cs = iter(clist)   # Iterators produce each item only once
    ds = iter(dlist)
    c = next(cs)
    d = next(ds)
    result = []
    while True:
        if c <= d:
            result.append(c)
            try:
                c = next(cs)
            except StopIteration:  # exhausted c before d
                result.append(d)
                result.extend(ds)
                return result
        else:  # c > d
            result.append(d)
            try:
                d = next(ds)
            except StopIteration:
                result.append(c)
                result.extend(cs)
                return result

显然,通过平等对待这些名单可以统一这一点。此特定版本首选首先放置第一个列表中的项目。

请注意del somelist[0]是最昂贵的项目删除操作;它移动除第一个以外的所有条目。 deque支持更有效的popleft方法(但是当你创建许多小实例时会更昂贵,而mergesort会这样做)。