Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 改进合并排序_Python_Algorithm - Fatal编程技术网

Python 改进合并排序

Python 改进合并排序,python,algorithm,Python,Algorithm,我正在练习合并排序,我很好奇我的第二个版本是否比第一个更好——这似乎是在内存需求方面,因为我是从列表中弹出的,而不是仅仅移动索引 第1版: def mergesort(L): if len(L)<=1: return L pivot=len(L)/2 left=mergesort(L[:pivot]) right=mergesort(L[pivot:]) i=j=0 sortedArr=[] while i<len(left)

我正在练习合并排序,我很好奇我的第二个版本是否比第一个更好——这似乎是在内存需求方面,因为我是从列表中弹出的,而不是仅仅移动索引

第1版:

def mergesort(L):
    if len(L)<=1: return L
    pivot=len(L)/2
    left=mergesort(L[:pivot])
    right=mergesort(L[pivot:])
    i=j=0
    sortedArr=[]
    while i<len(left) and j<len(right):
        if left[i]<right[j]:
            sortedArr.append(left[i])
            i+=1
        else:
            sortedArr.append(right[j])
            j+=1
    return sortedArr + left[i:] + right[j:]
def合并排序(L):

如果len(L)为什么不使用集合中的deque?它将降低popleft()操作的成本?

对于列表
L
L[:n]
操作是Python中的
O(n)
时间,
O(n)
空间(它创建了一个包含
n
元素的新列表)

给定
a
b
c
列表,
a+b+c
O(n)
时间和空间,其中
n
len(a)+len len(b)+len len(c)
(它还创建了一个包含
n
元素的新列表)

因此,每次调用
mergesort()
都需要时间和空间,即
T(n)=O(n*log(n))

由于
left.pop(0)
O(len(left))
操作,您的第二个版本的时间复杂度更差。第二个版本的内存需求与第一个版本的内存需求大致相同

下面是
O(n*log(n))
time,
O(n)
space解决方案,具有相同的结构(使用Python 3.3+语法):

def合并排序(L):
返回列表(合并\排序\生成(L,0,len(L)))
def merge_sort_gen(L,start,n):#O(n*log(n))时间,O(n)空间
如果n==1:#始终对一个元素的列表进行排序
收益率L[起点]
elif n>1:#对半部分进行排序并合并它们
一半=n//2
合并产生的收益(合并、排序、生成(L、开始、一半),
合并\排序\生成(L,开始+一半,n-一半))
其中
merge()
合并两个排序的迭代器。您可以使用或:

从functools导入部分
def merge(sorted_a,sorted_b,done=object()):#O(n)时间,O(1)空间
下一步a,下一步b=部分(下一步,已排序a,完成),部分(下一步,已排序b,完成)
a、 b=下一个a(),下一个b()
当a未完成且b未完成时:
如果b
你可以

从iterable获得的收益
产生与相同的项目(但内部细节不同):

iterable中项目的
:
收益项目

请参阅。

从列表前面弹出将非常低效。就内存而言,使用版本2可能会更好,但在计算方面,每个
pop
都需要python将列表内存中的元素向左移动1,这将非常低效。我想您可以反转列表并弹出结尾来修复…@mgilson正在反转一个昂贵的列表?在非常优化的python代码中应该是O(N)。(您可以通过
lst[::-1]
)来完成。请注意,在递归调用期间,您正在使用O(NlogN)额外内存。如果您想要一个内存高效的版本,就不应该对原始列表进行切片,而应该传递切片的开始索引和结束索引。
def mergesort(L):
    if len(L)<=1: return L
    pivot=len(L)/2
    left=mergesort(L[:pivot])
    right=mergesort(L[pivot:])
    sortedArr=[]
    while left!=[] and right!=[]:
        if left[0]<right[0]:
            sortedArr.append(left.pop(0))
        else:
            sortedArr.append(right.pop(0))
    return sortedArr + left + right