什么是归并排序?

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路[归并].

算法描述

  • 把长度为n的输入序列分成两个长度为n/2的子序列;

  • 对这两个子序列分别采用归并排序;

  • 将两个排序好的子序列合并成一个最终的排序序列。

归并操作

归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。

设有数列{6,202,100,301,38,8,1}

初始状态:6,202,100,301,38,8,1

第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;

第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;

第三次归并后:{1,6,8,38,100,202,301},比较次数:4;

总的比较次数为:3+4+4=11;

逆序数为14;

归并操作的原理

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾

将另一序列剩下的所有元素直接复制到合并序列尾

代码实现

public class MergeSort {
    private static int count = 1;
    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 7, 1, 3, 6, 2, 9, 10};
        int[] temp = new int[arr.length];
        split(arr, 0, arr.length - 1, temp);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 递归拆分数组然后合并
     *
     * @param arr   待拆分数组
     * @param left  数组左边下标
     * @param right 数组右下标
     * @param temp  用于存放合并后的有序序列的数组
     */
    public static void split(int[] arr, int left, int right, int[] temp) {
        if (left >= right) {
            return;
        }
        System.out.println("拆分第"+(count++)+"次");
        int mid = left + (right - left) / 2;
        //向左拆分
        split(arr, left, mid, temp);
        //向右拆分
        split(arr, mid + 1, right, temp);
        //每次拆分后都执行合并
        merge(arr, left, mid, right, temp);
    }

    /**
     * 合并两个各自有序序列(以mid为界)
     *
     * @param arr   原始数组
     * @param left  数组左边下标
     * @param mid   数组中间下标
     * @param right 数组右边下标
     * @param temp  用于存放新的有序数组
     */
    public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left;
        int j = mid + 1;
        //temp中的原始下标
        int t = 0;

        while (i <= mid && j <= right) {
            //两边数组都没有比较完 继续
            if (arr[i] < arr[j]) {
                //左边数组中值更小
                temp[t] = arr[i];
                i++;
            } else {
                //右边数组中值更小
                temp[t] = arr[j];
                j++;
            }
            t++;
        }
        //有一边已经全部复制到temp中了
        if (i <= mid) {
            //左边还没有复制完,将左边全部元素复制到temp中
            while (i <= mid) {
                temp[t] = arr[i];
                i++;
                t++;
            }
        } else if (j <= right) {
            //右边还没有复制完,将右边全部元素复制到temp中
            while (j <= right) {
                temp[t] = arr[j];
                j++;
                t++;
            }
        }
        //将temp复制到原arr中
        t = 0;
        while (left <= right) {
            arr[left] = temp[t];
            left++;
            t++;
        }
    }
}

复杂度

归并排序把集合一层一层进行折半分组。如果集合长度是n,那么折半的层数就是logn,每一层进行归并操作的运算量是n。所以归并排序的时间复杂度等于每一层的运算量乘以层级数,即O(nlogn)=。
我们再看空间复杂度,由于每次归并所创建的的额外集合都会随着方法的结束而被释放,因此这部分空间不应该累计,单次归并操作开辟的最大的空间是n,所以归并排序的空间复杂度是O(n)。


总结

归并排序的执行原理,主要分为以下步骤:

1.递归的方式进行拆分,将大的数组拆分成小的数组,直到剩余一个不能拆分

2.回溯的时候进行合并,合并时以mid为界,左右两边各自有序,通过额外的空间temp数组,将两个有序数组合并到一个有序数组中

3.将合并后的数组复制到原数组中,当回溯完成时整个数组有序

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容

  • 归并排序的归并这两个字和递归没有关系,归并是将两个有序的数组归并成一个更大的有序数组,但整个排序算法是有可能跟递归...
    我脱下短袖阅读 360评论 0 0
  • 一、对比分析图 均按从小到大排列 k代表数值中的"数位"个数 n代表数据规模 m代表数据的最大值减最小值 稳定性:...
    leo567阅读 1,223评论 0 1
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 1,239评论 0 2
  • 排序的基本概念 在计算机程序开发过程中,经常需要一组数据元素(或记录)按某个关键字进行排序,排序完成的序列可用于快...
    Jack921阅读 1,418评论 1 4
  • 归并排序和快速排序都用到了分治思想,非常巧妙。我们可以借鉴这个思想,来解决非排序的问题。 归并排序 归并排序的核心...
    被吹落的风阅读 1,323评论 0 3