我正在尝试实施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
的值也未更新。
答案 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会这样做)。