我想计算使用mergesort对列表进行排序时列表中有多少个反转。到目前为止,这是我的代码,其中' x'计算倒数的大小,而其余的则对其进行排序:
import sys
x = 0
def merge_sort(A):
merge_sort2(A, 0, len(A) - 1)
def merge_sort2(A, first, last):
if first < last:
middle = (first + last) // 2
merge_sort2(A, first, middle)
merge_sort2(A, middle + 1, last)
merge(A, first, middle, last)
def merge(A, first, middle, last):
global x
L = A[first:middle + 1]
R = A[middle + 1:last + 1]
L.append(sys.maxsize)
R.append(sys.maxsize)
i = j = 0
for k in range(first, last + 1):
if L[i] <= R[j]:
A[k] = L[i]
i += 1
else:
A[k] = R[j]
j += 1
x += 1
x += len(L[first + 1:])
当我使用列表调用合并排序时,变量x支持在列表中给出反转量。所以如果列表是&#39; [4,3,2,1],x将是6.如果列表是[1,2,3] x将是0.我改变x的值只要右边是但是,在合并定义中大于左边的数字总是太大了。我做错了什么?
答案 0 :(得分:0)
检查我的工作,但我认为不是:
x += 1
x += len(L[first + 1:])
你想要:
x += middle + 1 + j - k
基本上,你想要添加项目k实际来自哪里之间的差异,以及如果所有内容都已经排序,你希望它来自哪里。
答案 1 :(得分:0)
您的合并步骤对我来说有点难以理解 - 我不确定您为什么这样做(也许只是另一种合并方式?):
L.append(sys.maxsize)
R.append(sys.maxsize)
但是我无法通过添加到分区的额外元素来解决所有问题。而且我认为你最终将L
中的额外元素作为反转进行计数,每次合并都从R
我认为这会导致一些问题。但是你还有另外两个问题:
你的最后一行不是正确的逻辑:
x += len(L[first + 1:])
反转的数量将是你跳过的L
中的元素数量。你每次都计算L
的几乎所有元素。这样的事情效果更好:
x += len(L[i:])
然后在最后,你可能还剩下你还没有计算过的倒数的元素。也许这不是你的额外元素的问题,而是在更传统的合并中。这是我计算反转的方式:
def merge(A, first, middle, last):
global x
L = A[first:middle+1]
R = A[middle+1:last+1]
i = j = 0
k = first
print(L, R)
while i<len(L) and j<len(R):
if L[i] <= R[j]:
A[k] = L[i]
i += 1
else:
A[k] = R[j]
j += 1
# count how many left in L
x += len(L[i:])
k += 1
# take care of any leftovers in L or R
while i < len(L):
A[k] = L[i]
i += 1
k+=1
while j < len(R):
A[k] = R[j]
j += 1
k+=1
x += len(L[i:])