归并排序算法及分析

归并排序采用的是分治策略思想

归并排序是递归排序,思路是将数据表持续分裂为两半,对两半分别进行归并排序

递归的基本结束条件是:数据表仅有1个数据项,自然是排好序的

缩小规模:将数据表分裂为相等的两半,规模减为原来的二分之一

调用自身:将两半分别调用自身排序,然后将分别排好序的两半进行归并,得到排好序的数据表

归并排序:图示


归并排序:代码 


package com.zyj.test;

import java.util.Arrays;

/**
 * 归并排序算法实现和分析
 *
 * @author 张永俊
 */
public class DemoTest {
    public static void main(String[] args) {
        int[] arr = new int[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
        int[] temp = new int[arr.length];
        mergeSort(arr, temp, 0, arr.length - 1);
        System.out.println(Arrays.toString(temp));
    }

    public static void mergeSort(int[] arr, int[] temp, int left, int right) {

        /*判断左是否小于右指针,如果条件不成立则表示数据表只有一个数值*/
        if (left < right) {

            /*获取中间值*/
            int middle = (left + right) >> 1;

            /*将数据表拆分成左半部分和右半部分*/
            mergeSort(arr, temp, left, middle);
            mergeSort(arr, temp, middle + 1, right);

            /*此时左半部分和右半部分都是有序的,对两部分进行汇和*/
            merge(arr, temp, left, middle, right);
        }
    }

    public static void merge(int[] arr, int[] temp, int left, int middle, int right) {

        /*定义左半部分遍历起始位置*/
        int low1 = left;
        /*定义右半部分遍历起始位置*/
        int low2 = middle + 1;

        /*定义临时数据初始位置*/
        int pos = left;

        /*判断两部分指针的位置,有任何一方到达数据表尾部,停止循环*/
        while (low1 <= middle && low2 <= right) {

            /*升序排列小的放前,大的放后*/
            if (arr[low1] < arr[low2]) {

                temp[pos++] = arr[low1++];

            } else {

                temp[pos++] = arr[low2++];

            }

        }

        /*如果左半部分没有执行完,则继续执行*/
        while (low1 <= middle) {

            temp[pos++] = arr[low1++];

        }

        /*如果右半部分没有执行完,则继续执行*/
        while (low2 <= right) {

            temp[pos++] = arr[low2++];

        }

        /*将存在临时表的数据覆盖到原始数据表,进行下一轮排序*/
        while (left <= right) {

            arr[left] = temp[left++];

        }
    }
}

输出结果: 

 

 归并排序:算法分析


将归并排序分为两个过程来分析:分裂归并

分裂的过程,借鉴二分查找中的分析结果,是对数复杂度,时间复杂度为O(log n)

归并的过程,相对于分裂的每个部分,其所有数据项都会被比较和放置一次,所以是线性复杂度,其时间是O(n)

综合考虑,每次分裂的部分都进行一次O(n)的数据项归并,总的时间复杂度是O(nlog n)

最后,我们还是注意到两个切片操作

为了时间复杂度分析准确起见,可以通过取消切片操作,改为传递两个分裂部分的起始点和终止点,也是没问题的,只是算法可读性稍微牺牲一点点。

我们注意到归并排序算法使用了额外1倍的存储空间用于归并

这个特性在对待大数据集进行排序的时候要考虑进去

所以在Hadoop中MapReduce都是在各自分区中先进行快速排序,Combiner阶段再进行归并排序,节约内存资源

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值