我是初学者,学习有趣的算法,我正在尝试在Python中实现合并排序。
以下是我的实施。当我提供100000个列表时它非常慢。
def mergesortedlist(L, R):
LR = [0]*(len(L)+len(R)) ##merged output (LR combined)
i= 0 ##counter for left side
j= 0 ##counter for ride side
k = 0
while i <= len(L) and j <= len(R):
if i == len(L):
LR[k:]= R[j:]
return LR
elif j == len(R):
LR[k:] = L[i:]
return LR
elif L[i] < R[j]:
LR[k]= L[i]
i+=1
k+=1
else: ##left side is bigger than right side
LR[k]=R[j]
j+=1
k+=1
def mergesort(N):
if len(N) <= 1:
return N
else:
sub1 = N[0:round(len(N)/2)]
sub2 = N[round(len(N)/2):]
return mergesortedlist(mergesort(sub1), mergesort(sub2))
以下是我在本网站(http://interactivepython.org/courselib/static/pythonds/SortSearch/TheMergeSort.html)
上在线找到的实施方案def mergeSort(alist):
print("Splitting ",alist)
if len(alist)>1:
mid = len(alist)//2
lefthalf = alist[:mid]
righthalf = alist[mid:]
mergeSort(lefthalf)
mergeSort(righthalf)
i=0
j=0
k=0
while i < len(lefthalf) and j < len(righthalf):
if lefthalf[i] < righthalf[j]:
alist[k]=lefthalf[i]
i=i+1
else:
alist[k]=righthalf[j]
j=j+1
k=k+1
while i < len(lefthalf):
alist[k]=lefthalf[i]
i=i+1
k=k+1
while j < len(righthalf):
alist[k]=righthalf[j]
j=j+1
k=k+1
print("Merging ",alist)
alist = [54,26,93,17,77,31,44,55,20]
mergeSort(alist)
print(alist)
速度非常快。
据我所知,我的实现也是O(Nlog(N)),为什么我的速度慢得多?
感谢您的帮助。
干杯!
答案 0 :(得分:0)
我没有看到巨大的性能差异:对于1,000,000个随机浮点数,7.3s对5.4s。但你纠正第二个更快。
以下是如何对其进行分析以了解花费时间的事情。
python -m cProfile -s time mergesort.py
你的输出:
999999 8.517 0.000 11.088 0.000 mergesort.py:2(mergesortedlist)
1999999/1 2.735 0.000 14.151 14.151 mergesort.py:25(mergesort)
84184856/84184834 2.725 0.000 2.725 0.000 {len}
1999998 0.174 0.000 0.174 0.000 {round}
第二个:
ncalls tottime percall cumtime percall filename:lineno(function)
1999999/1 7.377 0.000 8.721 8.721 mergesort2.py:1(mergeSort)
40499148/40499126 1.344 0.000 1.344 0.000 {len}
你看到你的花费更多时间来调用len()和round()。
当你的数组返回数组时,第二个操作是通过引用传递的数组。复制也可能需要一些时间。由于您是初学者,因此查看difference
是有意义的答案 1 :(得分:0)
我的2美分。
在我的测试中,round()
或len()
函数都不会显着影响运行时间。
我认为问题如下:在每个mergesortedlist()
调用中,您创建一个新列表。
我用IPython的%%timeit
L = N[0:round(len(N)/2)]
R = N[round(len(N)/2):]
LR = [0]*(len(L)+len(R))
2,000,000个元素 - &gt; 10个循环,最佳3:34.4 ms每循环
1,000,000个元素 - &gt; 100循环,最佳3:每循环17.2毫秒
500,000个元素 - &gt; 100循环,最佳3:每循环8.3毫秒
250,000个元素 - &gt; 100循环,最佳3:3.49毫秒每循环
125,000个元素 - &gt; 1000循环,最佳3:每循环1.25毫秒
62,500个元素 - &gt; 1000循环,最佳3:每循环526μs
所以...
请记住,Mergesort的最坏情况是O(N * logN)。 (这个事实拒绝了我们将第一个排序函数应用于随机数而第二个排序到排序数字的情况。)