在Python中,如何计算合并排序算法中的交换
我已经完成了MergeSort算法,但我不知道如何计算交换 我的代码是:在Python中,如何计算合并排序算法中的交换,python,mergesort,Python,Mergesort,我已经完成了MergeSort算法,但我不知道如何计算交换 我的代码是: def mergesortInv(list): if len(list) < 2: return list else: middle = len(list) // 2 left = mergesortInv(list[:middle]) #definim les dues meitats right = mergesortInv(li
def mergesortInv(list):
if len(list) < 2:
return list
else:
middle = len(list) // 2
left = mergesortInv(list[:middle]) #definim les dues meitats
right = mergesortInv(list[middle:])
swaps=???
return mergeInv(left, right,swaps)
def mergeInv(left, right,swaps):
if len(left) < 1:
return right
if len(right) < 1:
return left
if left[0] <= right[0]:
return [left[0]] + mergeInv(left[1:],right,swaps)
else:
return [right[0]] + mergeInv(left,right[1:],swaps)
def mergesortInv(列表):
如果len(列表)<2:
返回列表
其他:
middle=len(列表)//2
左=合并(列表[:中间])#定义应付账款
right=mergesortInv(列表[中间:)
互换=???
返回合并投资(左、右、互换)
def合并投资(左、右、互换):
如果len(左)小于1:
返回权
如果len(右)<1:
左转
如果左[0]这是一个稍微修改过的代码版本,它似乎可以工作:
def mergesortInv(list, mergeInv):
if len(list) < 2:
return list, 0
else:
middle = len(list) // 2
left, lc = mergesortInv(list[:middle], mergeInv) #definim les dues meitats
right, rc = mergesortInv(list[middle:], mergeInv)
merge, mc = mergeInv(left, right)
return merge, lc + rc + mc
def mergeInvRec(left, right):
if len(left) < 1:
return right, 0
if len(right) < 1:
return left, 0
if left[0] <= right[0]:
res, cnt = mergeInvRec(left[1:], right)
return [left[0]] + res, cnt
else:
res, cnt = mergeInvRec(left, right[1:])
return [right[0]] + res, len(left) + cnt
def mergeInvFlat(left, right):
res, cnt = [], 0
il, ir = 0, 0
nl, nr = len(left), len(right)
while il < nl and ir < nr:
if left[il] <= right[ir]:
res.append(left[il])
il += 1
else:
res.append(right[ir])
ir += 1
cnt += nl - il
res.extend(left[il:])
res.extend(right[ir:])
return res, cnt
def mergesortInv(列表,mergeInv):
如果len(列表)<2:
返回列表,0
其他:
middle=len(列表)//2
左,lc=mergesortInv(列表[:中间],mergeInv)#定义应付账款
右,rc=mergesortInv(列表[中间:],mergeInv)
合并,mc=合并投资(左、右)
返回合并,lc+rc+mc
def MERGINVREC(左、右):
如果len(左)小于1:
返回右侧,0
如果len(右)<1:
向左返回,0
如果左[0]这是一个稍微修改过的代码版本,它似乎可以工作:
def mergesortInv(list, mergeInv):
if len(list) < 2:
return list, 0
else:
middle = len(list) // 2
left, lc = mergesortInv(list[:middle], mergeInv) #definim les dues meitats
right, rc = mergesortInv(list[middle:], mergeInv)
merge, mc = mergeInv(left, right)
return merge, lc + rc + mc
def mergeInvRec(left, right):
if len(left) < 1:
return right, 0
if len(right) < 1:
return left, 0
if left[0] <= right[0]:
res, cnt = mergeInvRec(left[1:], right)
return [left[0]] + res, cnt
else:
res, cnt = mergeInvRec(left, right[1:])
return [right[0]] + res, len(left) + cnt
def mergeInvFlat(left, right):
res, cnt = [], 0
il, ir = 0, 0
nl, nr = len(left), len(right)
while il < nl and ir < nr:
if left[il] <= right[ir]:
res.append(left[il])
il += 1
else:
res.append(right[ir])
ir += 1
cnt += nl - il
res.extend(left[il:])
res.extend(right[ir:])
return res, cnt
def mergesortInv(列表,mergeInv):
如果len(列表)<2:
返回列表,0
其他:
middle=len(列表)//2
左,lc=mergesortInv(列表[:中间],mergeInv)#定义应付账款
右,rc=mergesortInv(列表[中间:],mergeInv)
合并,mc=合并投资(左、右)
返回合并,lc+rc+mc
def MERGINVREC(左、右):
如果len(左)小于1:
返回右侧,0
如果len(右)<1:
向左返回,0
如果左[0]我没有测试这一点,但这只是为了让您了解我在对您的问题的评论中提出的建议
def mergesortInv(list):
if len(list) < 2:
return list
else:
middle = len(list) // 2
left = mergesortInv(list[:middle]) #definim les dues meitats
right = mergesortInv(list[middle:])
# swaps=???
return mergeInv(left, right)
def mergeInv(left, right):
""" return a tuple of total swaps and the merged list """
if len(left) < 1:
return (0, right)
if len(right) < 1:
return (0, left)
if left[0] <= right[0]:
swaps, lst = mergeInv(left[1:],right)
return (swaps, [left[0]] + [lst])
else:
swaps, lst = mergeInv(left,right[1:])
return (swaps + 1, [right[0]] + [lst])
我没有对此进行测试,但这只是为了让您了解我在对您的问题的评论中提出的建议
def mergesortInv(list):
if len(list) < 2:
return list
else:
middle = len(list) // 2
left = mergesortInv(list[:middle]) #definim les dues meitats
right = mergesortInv(list[middle:])
# swaps=???
return mergeInv(left, right)
def mergeInv(left, right):
""" return a tuple of total swaps and the merged list """
if len(left) < 1:
return (0, right)
if len(right) < 1:
return (0, left)
if left[0] <= right[0]:
swaps, lst = mergeInv(left[1:],right)
return (swaps, [left[0]] + [lst])
else:
swaps, lst = mergeInv(left,right[1:])
return (swaps + 1, [right[0]] + [lst])
交换在mergeInv
方法的else
部分中进行。如果你每次到那里都增加一个指数,那应该代表最后的总互换量。但您可能必须更改建议的函数签名。保留一个全局索引(坏)或返回每个mergeInv
调用中的掉期数量并累积它们(好)。请参阅。这里的答案显示了如何使用mergesort计算反转,但是还有其他方法可以做到这一点。请参阅我的答案,其中比较了不同列表大小上各种算法的速度。@Anubis我将尝试您给我的最后一个选项,顺便说一句,使用list
作为变量名不是一个好主意,因为这会影响内置的list
类型。在这里它不会伤害任何东西,但是它会使阅读代码有点混乱。如果出于某种原因,你试图在mergesortInv
中使用list
来创建一个列表,你会得到一条神秘的错误消息。我使用list
是因为它是一个中性名称,但在我最初的算法中,我得到了另一个名称。交换发生在mergeInv
方法的else
部分中。如果你每次到那里都增加一个指数,那应该代表最后的总互换量。但您可能必须更改建议的函数签名。保留一个全局索引(坏)或返回每个mergeInv
调用中的掉期数量并累积它们(好)。请参阅。这里的答案显示了如何使用mergesort计算反转,但是还有其他方法可以做到这一点。请参阅我的答案,其中比较了不同列表大小上各种算法的速度。@Anubis我将尝试您给我的最后一个选项,顺便说一句,使用list
作为变量名不是一个好主意,因为这会影响内置的list
类型。在这里它不会伤害任何东西,但是它会使阅读代码有点混乱。如果出于某种原因,你试图在mergesortInv
中使用list
来创建一个列表,你会得到一条神秘的错误消息。我使用list
是因为它是一个中性名称,但在我最初的算法中,我有另一个名称。好的,我抓住了now@ZRTSTR请注意,此代码将失败,原因是RecursionError:在包含1000项或更多项的列表上,相比之下,
超过了最大递归深度。@pm2捕捉良好。会更新的。好多了!而且速度也快了一点。当列表大小超过40左右时,它现在比我的timeit测试中大多数其他基于mergesort的版本都快。@PM2Ring刚刚查看了您的链接答案。印象深刻您似乎对该主题感兴趣;-]好的,我抓到了now@ZRTSTR请注意,此代码将失败,原因是RecursionError:在包含1000项或更多项的列表上,相比之下,
超过了最大递归深度。@pm2捕捉良好。会更新的。好多了!而且速度也快了一点。当列表大小超过40左右时,它现在比我的timeit测试中大多数其他基于mergesort的版本都快。@PM2Ring刚刚查看了您的链接答案。印象深刻您似乎对该主题感兴趣;-]这不管用mergeInv
返回一个元组,因此mergesortInv
也返回元组,但在mergesortInv
中,您有left=mergesortInv(list[:middle])
和right=mergesortInv(list[middle:])
两个left
和right
获得分配给它们的元组。此外,在mergeInv
中,您可以使用[left[0]]+[lst]
和[right[0]]+[lst]
创建嵌套列表。顺便说一句,元组是由逗号而不是括号构造的,只有在某些情况下才需要括号以防止歧义。所以您可以这样做,例如返回0,对吧
。这不起作用mergeInv
返回一个元组,因此mergesortInv
也返回元组,但在mergesortInv
中,您有left=mergesortInv(list[:middle])
和right=mergesortInv(list[middle:])
两个元组<