美文网首页
归并排序

归并排序

作者: 缓慢移动的蜗牛 | 来源:发表于2018-09-29 17:13 被阅读0次

思想:

归并基本思想是将两个(或以上)有序的序列合并成一个新的有序序列。
当然,此处介绍的归并排序主要是将两个有序的数据序列合并成一个新的有序序列。
细化来说,归并排序先将长度为n的无序序列看成是n个长度为1的有序子序列,首先做两两合并,得到 n/2个长度为2的有序子序列,再做两两合并……不断地重复这个过程,最终可以得到一个长度为n的有序序列。

假设有如下数据序列。
21,30,49,30*,97,62,72,08,37,16,54
程序对其不断合并的过程如下图


从图中可以看出,长度为16的数据序列,只需经过4次合并。也就是说,对于长度为n的数据序列,只需经过log2n次合并。
对于归并排序而言,其算法关键就在“合并”。如何将两个有序的数据序列合并成一个新的有序序列?合并算法的具体步骤如下

  • 定义变量i,i从0开始,依次等于A序列中每个元素的索引。
  • 定义变量j,j从0开始,依次等于B序列中每个元素的索引。
  • 拿A序列中i索引处元素和B序列中j索引处的元素进行比较,将较小的复制到一个临时数组中。
  • 如果i索引处的元素小,i++;如果j索引处的元素小,j++。

不断地重复上面4个步骤,即可将A、B两个序列中的数据元素复制到临时数组中,直到其中一个数组中的所有元素都被复制到临时数组中。最后,再将另一个数组中多出来的元素全部复制到临时数组中,合并即完成,再将临时数组中数据复制回去即可。

public class MergeSort {

    /**
     * 利用归并排序算法对数组data进行排序
     * @param data
     */
    public static void mergeSort(DataWrap[] data) {
        sort(data, 0, data.length - 1);
    }

    /**
     * 将索引从left到right范围的数组元素进行归并排序
     * @param data
     * @param left  待排序的数组的第一个元素的索引
     * @param right 待排序的数组的最后一个元素的索引
     */
    private static void sort(DataWrap[] data, int left, int right) {
        if (left < right) {
            //找出中间索引
            int center = (left + right) / 2;

            //对左边数组进行递归
            sort(data, left, center);

            //对右边数组进行递归
            sort(data, center + 1, right);

            //合并
            merge(data, left, center, right);
        }
    }

    /**
     * 将两个数组进行归并,归并前两个数组已经有序,归并后依然有序
     * @param data
     * @param left  左边数组的第一个元素的索引
     * @param center    左边数组的最后一个元素的索引,center+1是右边数组第一个元素的索引
     * @param right 右边数组的最后一个元素的索引
     */
    private static void merge(DataWrap[] data, int left, int center, int right) {
        DataWrap[] tmpArr = new DataWrap[data.length];

        int mid = center + 1;
        //third记录中间数组的索引
        int third = left;
        int tmp = left;

        while (left <= center && mid <= right) {
            //从两个数组中取出小的放入中间数组
            if (data[left].compareTo(data[mid]) <= 0) {
                tmpArr[third++] = data[left++];
            }else{
                tmpArr[third++] = data[mid++];
            }
        }

        //把剩余部分依次放入中间数组
        while (mid <= right) {
            tmpArr[third++] = data[mid++];
        }
        while (left <= center) {
            tmpArr[third++] = data[left++];
        }

        //将中间数组中的内容复制拷回原数组
        //原left-right范围的内容被复制回原数组
        while (tmp <= right) {
            data[tmp] = tmpArr[tmp++];
        }
    }

    public static void main(String[] args) {
        DataWrap[] data = new DataWrap[]{
                new DataWrap(9, ""),
                new DataWrap(-16, ""),
                new DataWrap(21, "*"),
                new DataWrap(23, ""),
                new DataWrap(-30, ""),
                new DataWrap(-49, ""),
                new DataWrap(21, ""),
                new DataWrap(30, ""),
                new DataWrap(30, "")
        };

        System.out.println("排序前:\n" + Arrays.toString(data));
        mergeSort(data);
        System.out.println("排序后 :\n" + Arrays.toString(data));
    }
}

总结

归并排序的时间复杂度为:O(nlog2n)
归并排序算法的空间效率较差,它需要一个与原始序列同样大小的辅助序列
稳定的排序算法

相关文章

  • 排序算法

    约定 选择排序 冒泡排序 插入排序 希尔排序 归并排序1. 归并方法2. 自顶向下归并排序3. 自底向上归并排序 ...

  • 排序二:归并、快排

    文章结构 归并排序 快速排序 源码 1. 归并排序 1.1 什么是归并排序 归并排序的思想是:将待排序的区间平分成...

  • java归并排序

    归并排序什么是归并排序:图解归并排序归并排序有两种实现方式,一是基于递归,而是基于迭代1)基于递归的归并排序: 基...

  • 算法—排序篇2

    1、归并排序(Merging Sort) 归并排序(Merging Sort): 就是利用归并的思想实现排序⽅法....

  • 常见的排序算法(2)

    要点 快速排序 归并排序 1.快速排序 2.归并排序

  • 排序算法之归并排序

    归并排序(Merge Sort) 归并排序是利用归并的思想实现排序的方式,该算法采用的是经典的分治算法 归并排序过...

  • 算法 第二章第二部分笔记

    各种排序算法的性能特点 选择排序 插入排序 希尔排序 归并排序 本地归并排序 自底向上的归并排序 快速排序 三向切...

  • 归并排序(二路归并排序)

    归并排序的思路 归并排序是通过“归并”操作完成排序的,将两个或者多个有序子表归并成一个子表。归并排序是“分治法”的...

  • 算法排序之归并排序和快速排序

    归并排序和快速排序用的都是分治的思想,用递归的编程技巧来实现.咱们先来看归并排序. 归并排序 归并排序的核心思想就...

  • 基于左闭右开的乱序数组归并排序 2020-04-24(未经允许,

    归并排序代码模板 递归形式思路:二分nums数组后对nums的归并排序 = 对左侧数组归并排序+对右侧数组归并排序...

网友评论

      本文标题:归并排序

      本文链接:https://www.haomeiwen.com/subject/tdkboftx.html