merge sort是常用的一种排序方法,即归并排序,是分治算法的典型例子。
归并排序的优点:
a. 是基于比较算法排序的巅峰,算法时间复杂度为O(nlogn)
b. 是一种稳定的算法,即两个小大相同的数在排序的时候先后顺序不会变
缺点:
需要O(n)的空间辅助,即归并排序是牺牲了空间来提高时间复杂度
算法的思想:
a.给定一个数列,将数列分成左右两个数列,将左右两个数列进行排序,最后将这左右两个有序数列合成一个有序数列。
那么怎样对左右两个数列进行排列呢,同 a 方法一样,递归调用。
如果上述文字描述不是很清楚,下面借用一幅图对该算法进行解释
时间复杂度T(n)满足以下关系式:
T[n]=2T[n/2]+thita(n)
把两个序列合并起来的时间复杂度为 thita(n)
根据主定理,归并排序的时间复杂度为o(nlogn)
# 按照升序排列
def merge(right_half_, left_half_):
m_ = []
r_ = l_ = 0
while r_ < len(right_half_) and l_ < len(left_half_):
# 因为如果两个数大小一样,归并排序不会改变两个数的先后位置,所以这个if是<=
if left_half_[l_] <= right_half_[r_]:
m_.append(left_half_[l_])
l_ += 1
else:
m_.append(right_half_[r_])
r_ += 1
if r_ == len(right_half_):
for i in left_half_[l_:]:
m_.append(i)
else:
for i in right_half_[r_:]:
m_.append(i)
return m_
def merge_sort(L):
length = len(L)
if length == 1:
return L
middle = length // 2
right_half = merge_sort(L[:middle])
left_half = merge_sort(L[middle:])
return merge(right_half, left_half)
if __name__ == '__main__':
a = [14, 2, 34, 43, 21, 19]
print(merge_sort(a))
接下来我们再归并排序的基础上求序列的逆序对。
逆序对的定义:设a为一个有n个数字的有序集(n>1),其中所有数字各不相同。如果存在正整数i,j,使得 1<=i<j<=n 但是 a[i]>a[j], 则 <a[i],a[j]> 这个有序对称为A的一个逆序对。
算法:同样利用分治的思想求取逆序对。我们用PPT直接说明逆序对的求法
大概是这样的,先分别求取左右两个半序列内部的逆序对,最后求取两个之间的逆序对,最后将这三个逆序对相加就是整个序列的逆序对,代码对上面归并排序的代码稍微修改一下即可。代码如下
# 按照升序排列
def merge(right_half_, left_half_, right_count, left_count):
m_ = []
r_ = l_ = 0
count = 0
while r_ < len(right_half_) and l_ < len(left_half_):
# 因为如果两个数大小一样,归并排序不会改变两个数的先后位置,所以这个地方是< =
if left_half_[l_] <= right_half_[r_]:
m_.append(left_half_[l_])
l_ += 1
else:
m_.append(right_half_[r_])
r_ += 1
count += len(left_half_) - l_
if r_ == len(right_half_):
for i in left_half_[l_:]:
m_.append(i)
else:
for i in right_half_[r_:]:
m_.append(i)
return m_, count + right_count + left_count
def merge_sort(L):
length = len(L)
if length == 1:
return L, 0 # return多个变量不用()
middle = length // 2
left_half, right_inversion = merge_sort(L[:middle])
right_half, left_inversion = merge_sort(L[middle:])
return merge(right_half, left_half, right_inversion, left_inversion)
if __name__ == '__main__':
a = [1, 5, 4, 8, 10, 2, 6, 9, 3, 7]
# a = [14, 2, 34]
print(merge_sort(a))
输出结果为:
([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 17)
参考链接:https://blog.csdn.net/su_bao/article/details/81053871
https://www.cnblogs.com/x_wukong/p/6739740.html
https://blog.csdn.net/qq_35581662/article/details/52949431