数据结构---归并排序

def InversePairs(data):
    # write code here
    if not data:
        return 0
    copy = []
    for i in data:
        copy.append(i)
    length = len(data)
    count = InversePairsCore(data, copy, 0, length - 1)

    print(count%1000000007)
    return count%1000000007
def InversePairsCore(data, copy, start, end):
    if start == end:
        copy[start] = data[start]
        return 0

    length = int((end - start) / 2)
    left = InversePairsCore(copy, data, start, start + length)
    right = InversePairsCore(copy, data, start + length + 1, end)

    i = start + length
    j = end
    index_copy = end
    count = 0
    while i >= start and j >= start + length + 1:
        if data[i] > data[j]:
            copy[index_copy] = data[i]
            index_copy -= 1
            i -= 1
            count += j - start - length
        else:
            copy[index_copy] = data[j]
            index_copy -= 1
            j -= 1
    copy += data[start:i+1]
    copy += data[start + length + 1:j+1]
    return (left + right + count)

data = [364, 637, 341, 406, 747, 995, 234, 971, 571, 219, 993, 407, 416, 366, 315, 301, 601, 650, 418, 355, 460, 505, 360, 965, 516, 648, 727, 667, 465, 849, 455, 181, 486, 149, 588, 233, 144, 174, 557, 67, 746, 550, 474, 162, 268, 142, 463, 221, 882, 576, 604, 739, 288, 569, 256, 936, 275, 401, 497, 82, 935, 983, 583, 523, 697, 478, 147, 795, 380, 973, 958, 115, 773, 870, 259, 655, 446, 863, 735, 784, 3, 671, 433, 630, 425, 930, 64, 266, 235, 187, 284, 665, 874, 80, 45, 848, 38, 811, 267, 575]
InversePairs(data)

https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5

基本思想:

归并排序与之前的交换(快速)、选择(堆)等排序的思想不一样,“归并”的含义就是:

将两个或者两个以上的有序表组合成一个新的有序表,假定待排序表含有n个记录,则可以看做是n个有序的子表,每个子表的长度为1,然后两两归并,得到\left \lceil n/2 \right \rceil个长度为2或者为1的有序表;再两两归并,....如此重复,直到合并成一个长度为n的有序表为止,这种排序方法为2-路归并排序

初始关键字: 49  38  65  97  76  13  27

一趟归并后: 38  49  65  97  13  76  27

二趟归并后: 38  49  65  97  13  27  76

三趟归并后: 13  27  38  49  65  76  97

merge()的功能是将前后相邻的两个有序表归并成为一个有序表的算法。

设两段有序表A[low,...mid]、A[mid+1,...high]放在同一个有序表的两个位置上,先让它们复制到辅助数组B里面,每次从对应B中的两个段取出一个记录进行关键字的比较,先将小者放入A中,当数组B中有一段的下标超出其对应的表长时,即该段所有的元素已经完全复制到A中,另一端中的剩余部分直接复制到A中。

 

递归形式的2-路归并排序是基于分治的!过程如下:

  • 分解:将含有n个元素的待排序表分成各含有n/2个元素的子表,采用二路归并算法对两个子表递归的地进行排序
  • 合并:合并两个已排序的子表得到排序结果

代码如下:

# merge函数的功能是将前后相邻的两个有序子表归并成为一个有序表
# left和right就是两个前后相邻的有序子表,我们需要一个辅助数组result,最后返回的result就是最后的
# 归并排序结果
# i和j一起从0开始向后走,对应位置(不一定就是下标相同)谁小谁被收到result中去,然后下去的那个指针向
# 后走一个,直到最后
# 其实result += left[i:] 和 result += right[j:]只会执行一个,因为有一个已经被收光了。
def merge(left, right):
    i, j = 0, 0
    result = []
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result += left[i:]
    result += right[j:]
    return result
# 递归形式的二路归并算法是基于分治的
# 分解:将n个记录一分为2,然后对分开的两个各含有n/2个元素的子表递归调用自身
# 合并: 合并两个已经排序的子表得到结果
def merge_sort(lists):
    if len(lists) <= 1:
        return lists
    num = len(lists) /2
    left = merge_sort(lists[:num])
    right = merge_sort(lists[num:])
    return merge(left, right)


 

性能:

  • 空间:需要借助一个辅助数组B,所以空间复杂度为O(n)
  • 时间:每一趟归并就是一个while循环,即O(n),一共要\left \lceil log_{2} n\right \rceil趟归并,所以算法时间复杂度是O(nlogn)

稳定性:

merge不会改变相同关键字记录的相对次序,所以2路归并排序是一个稳定的排序算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值