java归并算法实例_归并排序——经典算法的简单实现

归并排序定义:

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

136be34314a57ba454d97dfa8ef5d707.png

其实就是先把数组范围分为无数的二等分,在二等分中,把两个有序数组归并成一个有序数组,在把另外两个有序数组归并成一个有序数组,之后把归并成的两个有序数组重新归并成一个新的有序数组,之后递归周而复始的把范围从小扩大到整个原来的要排序的数组范围.形成一个完整的有序数组。

归并排序步骤:

分成若干二等分

合并若个二等分

136be34314a57ba454d97dfa8ef5d707.png

所以整个排序的关键是合并函数mergeSort—–用于合并两个有序数组

归并排序原理

归并排序具体工作原理如下(假设序列共有n个元素):

将序列每相邻两个数字进行归并操作(merge),形成floor(n/2)个序列,排序后每个序列包含两个元素

将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素

重复步骤2,直到所有元素排序完毕

136be34314a57ba454d97dfa8ef5d707.png

归并排序示例:

自顶向下的归并排序

对一个数组排序先将左子数组排序,右子数组排序,最后合并形成最后的有序的数组,要对左子数组进行排序,采用同样的方式分割数组······

136be34314a57ba454d97dfa8ef5d707.png

以整数数组为例,代码如下:

136be34314a57ba454d97dfa8ef5d707.png

136be34314a57ba454d97dfa8ef5d707.png

上述为归并排序C++示例,可以看出一个规模为N的数组,归并排序所需时间和NlgN成正比,这方面相对于其他排序算法已经非常优秀了。

迭代版归并排序

136be34314a57ba454d97dfa8ef5d707.png

其中 merge 函数不变,修改 mergeSort 函数

136be34314a57ba454d97dfa8ef5d707.png

Python中的归并排序算法:

136be34314a57ba454d97dfa8ef5d707.png

Java实现归并排序

归并排序将一个长度为n的数组平均分为两个n/2的数组分别进行处理,因此,在sort方法中又调用了两次sort方法自身。当数组大小为1时,则认为该数组为已经为排好序的数组。因此在sort方法中,需要end与pos相差大于2时,才需要进一步拆分,这也是递归的终止条件。

136be34314a57ba454d97dfa8ef5d707.png

136be34314a57ba454d97dfa8ef5d707.png

在代码中,使用了Java提供的arraycory函数进行数组复制,这种直接复制内存区域的方式,将会比循环赋值的方式速度更快。有些算法实现会给merge方法中的两个临时数组设置哨兵,目的是为了防止merge中for循环的前两个if判断。为了方便理解,LZ这里没有设置哨兵,当某一个数组的元素消耗完时,将直接使用arraycopy方法把另外一个数组copy到numbers当中。

136be34314a57ba454d97dfa8ef5d707.png

总结:

归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值