【算法学习笔记05】分治思想之MergeSort合并排序

1 分治(Divide-and-Conquer)

分治的思想就是字面意义,“分而治之”。当我们拿到一个复杂问题时,如果不能够很好的解决,我们首先会想到的是将这个复杂的问题简单化。将原问题分成很多个子问题,再将子问题分成更小的子问题,直到他们是好解决能解决的。

分治法的基本思想:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

分治的基本步骤:

  • 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题
  • 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
  • 合并:将各个子问题的解合并为原问题的解

分治法的复杂性分析:分治时,将问题划分成很多子问题,这些子问题往往有很高的自相似,所以和递归的时间复杂度非常相似。其实递归就是实现很多分治算法的有效武器。用T(n)表示该分治法解规模为|P|=n的问题所需的计算时间: T(n)=kT(n/m)+f(n)

常见算法:二分搜索、合并排序、快速排序、汉诺塔问题。

2 Merge Sort 合并排序及其python实现

合并排序就是典型的采用分治算法来实现排序。按照之前讨论的分治的基本步骤,合并排序分为以下几个步骤:

分解:将需要排序的数组等分为左右两部分,直到不可再分割

解决:对分割好的子序列依次排序

合并:将排列好的子序列进行排序

以排列[ 1,3,4,6,8,9,5,2]的合并排序为例子:

 将数组对半分组,分到最小后进行排序合并。合并排序的优势在于,每次合并时都是在合并已经排列好的数组,大大减少了排序的开销。

算法实现:

采用分治的有效武器,递归来实现算法

分解部分:我们只需要将需要解决的数组进行对半分,直到分解到不能再分割(数组的大小等于1)

合并部分:已知我们合并的数组都是已经排列好的数组,如何合并两个有序数组呢。我们只需要从数组的第一位进行比较,将小的放进合并的第一位,更大的是第二位,接着比较第二位,以此类推。

合并部分的思路如下:

while len(left)>0 and len(right)>0:
    if left[0] < right[0]:
        res.append(left.pop(0))
    else:
        res.append(right.pop(0))
if len(left)>0:
    res.extend(left)
if len(right)>0:
    res.extend(right)


合并算法代码实现:

#合并排序
def merge(left,right):
    res=[]
    while len(left)>0 and len(right)>0:
        if left[0] < right[0]:
            res.append(left.pop(0))
        else:
            res.append(right.pop(0))
    if len(left)>0:
        res.extend(left)
    if len(right)>0:
        res.extend(right)
    return res

def merge_sort(arr:list):
    if len(arr)<2:
        return arr
    mid=len(arr) //2
    left=arr[:mid]
    right=arr[mid:]
    #不断将左右两部分再进行对半分
    left_sort=merge_sort(left)
    right_sort=merge_sort(right)

    return merge(left_sort,right_sort)

时间复杂度分析:

可知在对left和right排序的过程中是遍历数组,时间复杂度是O(N)。在将数组对半分的时候(分成left和right),时间复杂度时O(logN),类比二分法可知:

归并排序的时间复杂度为O(nlogn),其执行效率与要排序的原始数组的有序程度无关。
 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值