算法基础:排序(二)——归并排序——Python实现

本文详细介绍了归并排序的分治策略,包括自顶向下、自底向上和插入排序优化的实现方法,并通过测试对比展示了不同规模数组的排序效率,验证了归并排序O(nlogn)的时间复杂度优势。
摘要由CSDN通过智能技术生成

1. 归并排序与分治策略

归并排序的核心思想就是 分而治之

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

分治策略:对于一个规模为N(N较大)的问题,将其划分为K个规模较小的子问题,若子问题相互独立且与原问题形式相同,我们则可以使用递归不断地将子问题进行划分,将一个大问题自顶向下一层层划分为容易解得小问题,得到小问题的解后再自底向上逐层合并得到原问题的解。

归并排序就是采用了这样的分治策略来设计算法。对于一个长度为N的数组,通过逐层二分将大数组分解成容易排序的小数组,然后对排好序的两个子数组进行归并,最终得到归并后的有序数组。

使用增量策略的排序(如插入排序)的算法复杂度为O(n^2),而使用分治策略的归并排序则将算法复杂度降到了O(nlogn)。经过测试,这种排序算法的优化效果是很显著的,大家可以在最后看到测试时各种方法所用时间的对比。


2. 自顶向下、自底向上、使用插入排序的归并算法实现

(1)归并算法

有了分治的策略,那么我们如何将排好序的子数组合并成一个有序的数组呢?这就是归并排序的核心算法merge(a,lo,mid,hi)。

归并

对于上图看了代码应该很容易理解:
需要一个辅助数组aux,现将a的元素拷贝给aux,再将aux元素归并到a中。

    def __merge(self,a,lo,mid,hi):
        i=lo
        j=mid+1
        self.__aux[lo:hi+1]=a[lo:hi+1] #将a[lo..hi] 复制给aux[lo..hi]
        for k in range(lo,hi+1):
            if i > mid:#左侧元素归并完毕,将右侧剩余元素依次拷贝到a
                a[k] = self.__aux[j]
                j+=1
            elif j > hi:#右侧,同上
                a[k] = self.__aux[i]
                i+=1
            elif self.less(self.__aux[j],self.__aux[i]):#谁小将谁归并入a
                a[k] = self.__aux[j]
                j+=1
            else:
                a[k] = self.__aux[i]
                i+=1

(2)自顶向下的归并排序

有了以上的归并操作后,我们如何递归地划分数组并将两个子数组排序呢?通过递归直到将子数组划分为长度为1的数组,此时hi <= lo开始return,归并后的数组即是长度为2,4,8,…,n的有序数组。

   def __sort_by_recurse(self,a,lo,hi): # 使用递归进行自顶向下归并
        if hi <= lo:
            return
        mid=int((hi+lo)/2)
        self.__sort_by_recurse(a,lo,mid)
        self.__sort_by_recurse(a,mid+
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值