资讯专栏INFORMATION COLUMN

归并排序

CoyPan / 793人阅读

摘要:概述归并排序法是将两个或两个以上有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。

概述

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序采用的是递归来实现,属于“分而治之”,将目标数组从中间一分为二,之后分别对这两个数组进行排序,排序完毕之后再将排好序的两个数组“归并”到一起,归并排序最重要的也就是这个“归并”的过程,归并的过程中需要额外的跟需要归并的两个数组长度一致的空间。

效果图:

步骤

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

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

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

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

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

实例

原始数据:

3 5 2 6 2

归并的前提是将数组分开,一分为二,再一分为二,分到不能再分,进行归并。

第一轮分隔,索引2 ((0+4)/2=2) 为中间

[3 5 2] [6 2]

第二轮分隔,对[3 5 2]进行分隔

[3 5] [2] [6 2]

第三轮分隔,对[3 5]进行分隔

[3] [5] [2] [6 2]

合并[3] [5]

[3 5] [2] [6 2]

合并[3 5] [2]

[2 3 5] [6 2]

第四轮分隔,对[6 2]进行分隔

[2 3 5] [6] [2]

合并[6] [2]

[2 3 5] [2 6]

合并[2 3 5] [2 6]

[2 2 3 5 6]
代码实现(Java)
package com.coder4j.main.arithmetic.sorting;

public class Merge {
    
    private static int mark = 0;

    /**
     * 归并排序
     * 
     * @param array
     * @param low
     * @param high
     * @return
     */
    private static int[] sort(int[] array, int low, int high) {
        int mid = (low + high) / 2;
        if (low < high) {
            mark++;
            System.out.println("正在进行第" + mark + "次分隔,得到");
            System.out.println("[" + low + "-" + mid + "] [" + (mid + 1) + "-" + high + "]");
            // 左边数组
            sort(array, low, mid);
            // 右边数组
            sort(array, mid + 1, high);
            // 左右归并
            merge(array, low, mid, high);
        }
        return array;
    }

    /**
     * 对数组进行归并
     * 
     * @param array
     * @param low
     * @param mid
     * @param high
     */
    private static void merge(int[] array, int low, int mid, int high) {
        System.out.println("合并:[" + low + "-" + mid + "] 和 [" + (mid + 1) + "-" + high + "]");
        int[] temp = new int[high - low + 1];
        int i = low;// 左指针
        int j = mid + 1;// 右指针
        int k = 0;
        // 把较小的数先移到新数组中
        while (i <= mid && j <= high) {
            if (array[i] < array[j]) {
                temp[k++] = array[i++];
            } else {
                temp[k++] = array[j++];
            }
        }
        // 两个数组之一可能存在剩余的元素
        // 把左边剩余的数移入数组
        while (i <= mid) {
            temp[k++] = array[i++];
        }
        // 把右边边剩余的数移入数组
        while (j <= high) {
            temp[k++] = array[j++];
        }
        // 把新数组中的数覆盖array数组
        for (int m = 0; m < temp.length; m++) {
            array[m + low] = temp[m];
        }
    }

    /**
     * 归并排序
     * 
     * @param array
     * @return
     */
    public static int[] sort(int[] array) {
        return sort(array, 0, array.length - 1);
    }

    public static void main(String[] args) {
        int[] array = { 3, 5, 2, 6, 2 };
        int[] sorted = sort(array);
        System.out.println("最终结果");
        for (int i : sorted) {
            System.out.print(i + " ");
        }
    }
}

测试输出结果:

正在进行第1次分隔,得到
[0-2] [3-4]
正在进行第2次分隔,得到
[0-1] [2-2]
正在进行第3次分隔,得到
[0-0] [1-1]
合并:[0-0] 和 [1-1]
合并:[0-1] 和 [2-2]
正在进行第4次分隔,得到
[3-3] [4-4]
合并:[3-3] 和 [4-4]
合并:[0-2] 和 [3-4]
最终结果
2 2 3 5 6 

经测试,与实例中结果一致。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65439.html

相关文章

  • 归并排序 - Algorithms, Part I, week 3 MERGESORTS

    摘要:两个单元素数组的合并实际就是对这两个数进行了排序,即变为,同样再对后一组的两个数归并排序,即变为,再将两单元数组归并成四单元数组即和归并为。 前言 本周讲解两个50多年前发明,但今天仍然很重要的经典算法 (归并排序和快速排序) 之一 -- 归并排序,几乎每个软件系统中都可以找到其中一个或两个的实现,并研究这些经典方法的新变革。我们的涉及范围从数学模型中解释为什么这些方法有效到使这些算法...

    Jokcy 评论0 收藏0
  • 归并排序就这么简单

    摘要:归并排序就这么简单从前面已经讲解了冒泡排序选择排序插入排序快速排序了,本章主要讲解的是归并排序,希望大家看完能够理解并手写出归并排序快速排序的代码,然后就通过面试了如果我写得有错误的地方也请大家在评论下指出。 归并排序就这么简单 从前面已经讲解了冒泡排序、选择排序、插入排序,快速排序了,本章主要讲解的是归并排序,希望大家看完能够理解并手写出归并排序快速排序的代码,然后就通过面试了!如果...

    ingood 评论0 收藏0
  • Java排序归并排序

    摘要:排序之归并排序简介归并排序的算法是将多个有序数据表合并成一个有序数据表。如果参与合并的只有两个有序表,则成为二路合并。对于一个原始的待排序数列,往往可以通过分割的方法来归结为多路合并排序。 Java排序之归并排序 1. 简介 归并排序的算法是将多个有序数据表合并成一个有序数据表。如果参与合并的只有两个有序表,则成为二路合并。对于一个原始的待排序数列,往往可以通过分割的方法来归结为多路合...

    gityuan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<