我已经完成了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)
此算法的输出将是排序列表(算法适用于此部分)和交换次数:mergesortInv(list) == ([1, 2, 3, 4, 5, 7, 8], 6)
6是交换次数。
答案 0 :(得分:3)
以下是您的代码的略微修改版本:
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
这主要是记账的问题。计算每一步的交换次数并添加它们。在最后一个分支中,right
的第一个元素一直在left
的每个元素之间冒泡,这就是为什么我们在len(left)
交换它们的原因。
编辑:正如@ PM2Ring指出mergeInv
中的递归有点鲁莽,并且对于中等大小的列表将超过Python的最大递归深度。
我添加了一个非递归版本。您可以通过将其名称作为第二个arg传递给main函数来在递归和非递归版本之间切换。
答案 1 :(得分:1)
我没有对此进行测试,但这只是为了让您了解我在您的问题评论中建议的内容。
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])
用法,
swaps, lst = mergesortInv(mylist)