使用归并排序的反转次数
Number of inversions using merge sort
我编写这段代码是为了使用 merge_sort
获取反转次数,但我没有得到正确的输出。谁能告诉我为什么输出错误?
def merge(B,C): # B,C are sorted
D = list()
count = 0
# empty list to get the merged list
while (B != []) and (C != []): # breaks if any one of B or C becomes empty
b = B[0] # to get first element of B
print("b",b)
c = C[0] # to get first element of C
print("c",c)
if b<=c:
B.remove(b) # if b<c remove b from B and add to D
D.append(b)
else:
C.remove(c) # if b>c remove c from C and add to D
D.append(c)
count += 1
print("count_in_merge",count)
# now if either one of B or C has become empty so while loop is exited
# so we can add remaining elements of B and C as it is to D as they are
# already sorted
if B != []:
for i in B:
D.append(i)
if C != []:
for i in C:
D.append(i)
return D, count
def sort_and_num(A):
if len(A) == 1:
return A,0
m = len(A) // 2
B,count_b = sort_and_num(A[0:m])
C,count_c = sort_and_num(A[m:])
A_,count = merge(B,C)
count += (count_b + count_c)
return A_, count
当我运行:
A = [ 9, 8 ,7, 3, 2, 1]
A_,c = sort_and_num(A)
print(A_,c)
输出为:
[1, 2, 3, 7, 8, 9] 9
但输出应该是
[1, 2, 3, 7, 8, 9] 15
另一方面,如果我输入:
A = [3,1,2,4]
A_, count = sort_and_num(A)
print(A_, count)
输出为:
[1,2,3,4 ] 3
这是正确的。哪里出错了?
在此代码片段中:
else:
C.remove(c) # if b>c remove c from C and add to D
D.append(c)
count += 1
您应该根据 B
列表
的其余部分的长度更新 count
count += len(B)
因为从右侧移动一个元素可能会同时“纠正”许多反转。
另请注意,由于会立即从列表中删除元素,因此选择的实现相当低效。
您的代码中存在一些问题:
- 要删除列表的第一个元素,您应该使用
pop()
,而不是 remove()
- 从
C
取元素时的反转次数是len(B)
,不是1
。
- 你应该加上每一半的反转次数和合并阶段的反转次数
sort_and_num
中的初始测试也应该测试一个空列表,return 它的计数为 0。
这是修改后的版本:
def merge(B, count_b, C, count_c): # B,C are sorted
D = []
count = count_b + count_c
# empty list to get the merged list
while (B != []) and (C != []): # breaks if any one of B or C becomes empty
if B[0] <= C[0]:
D.append(B.pop()) # if b<=c remove b from B and add it to D
else:
D.append(C.pop()) # if b>c remove c from C and add it to D
count += len(B) # moving c before all remaining elements of B
# now if either one of B or C has become empty so while loop is exited
# so we can add remaining elements of B and C as it is to D as they are
# already sorted
for i in B:
D.append(i)
for i in C:
D.append(i)
return D, count
def sort_and_num(A):
if len(A) <= 1:
return A,0
m = len(A) // 2
B,count_b = sort_and_num(A[:m])
C,count_c = sort_and_num(A[m:])
return merge(B, count_b, C, count_c)
我编写这段代码是为了使用 merge_sort
获取反转次数,但我没有得到正确的输出。谁能告诉我为什么输出错误?
def merge(B,C): # B,C are sorted
D = list()
count = 0
# empty list to get the merged list
while (B != []) and (C != []): # breaks if any one of B or C becomes empty
b = B[0] # to get first element of B
print("b",b)
c = C[0] # to get first element of C
print("c",c)
if b<=c:
B.remove(b) # if b<c remove b from B and add to D
D.append(b)
else:
C.remove(c) # if b>c remove c from C and add to D
D.append(c)
count += 1
print("count_in_merge",count)
# now if either one of B or C has become empty so while loop is exited
# so we can add remaining elements of B and C as it is to D as they are
# already sorted
if B != []:
for i in B:
D.append(i)
if C != []:
for i in C:
D.append(i)
return D, count
def sort_and_num(A):
if len(A) == 1:
return A,0
m = len(A) // 2
B,count_b = sort_and_num(A[0:m])
C,count_c = sort_and_num(A[m:])
A_,count = merge(B,C)
count += (count_b + count_c)
return A_, count
当我运行:
A = [ 9, 8 ,7, 3, 2, 1]
A_,c = sort_and_num(A)
print(A_,c)
输出为:
[1, 2, 3, 7, 8, 9] 9
但输出应该是
[1, 2, 3, 7, 8, 9] 15
另一方面,如果我输入:
A = [3,1,2,4]
A_, count = sort_and_num(A)
print(A_, count)
输出为:
[1,2,3,4 ] 3
这是正确的。哪里出错了?
在此代码片段中:
else:
C.remove(c) # if b>c remove c from C and add to D
D.append(c)
count += 1
您应该根据 B
列表
count
count += len(B)
因为从右侧移动一个元素可能会同时“纠正”许多反转。
另请注意,由于会立即从列表中删除元素,因此选择的实现相当低效。
您的代码中存在一些问题:
- 要删除列表的第一个元素,您应该使用
pop()
,而不是remove()
- 从
C
取元素时的反转次数是len(B)
,不是1
。 - 你应该加上每一半的反转次数和合并阶段的反转次数
sort_and_num
中的初始测试也应该测试一个空列表,return 它的计数为 0。
这是修改后的版本:
def merge(B, count_b, C, count_c): # B,C are sorted
D = []
count = count_b + count_c
# empty list to get the merged list
while (B != []) and (C != []): # breaks if any one of B or C becomes empty
if B[0] <= C[0]:
D.append(B.pop()) # if b<=c remove b from B and add it to D
else:
D.append(C.pop()) # if b>c remove c from C and add it to D
count += len(B) # moving c before all remaining elements of B
# now if either one of B or C has become empty so while loop is exited
# so we can add remaining elements of B and C as it is to D as they are
# already sorted
for i in B:
D.append(i)
for i in C:
D.append(i)
return D, count
def sort_and_num(A):
if len(A) <= 1:
return A,0
m = len(A) // 2
B,count_b = sort_and_num(A[:m])
C,count_c = sort_and_num(A[m:])
return merge(B, count_b, C, count_c)