在Python中,如何计算合并排序算法中的交换

在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

我已经完成了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(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:])
两个元组<