排序算法-归并排序

概述

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案”修补”在一起,即分而治之)。

速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。

算法稳定性

并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有 序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定 性。那么,在短的有序序列合并的过程中,稳定是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结 果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。

时间复杂度

平均时间复杂度均为O(nlogn)

归并过程

《排序算法-归并排序》

示例代码

/**
 * 归并排序
 * @author 吴庆龙
 * Date: 2018/8/2
 * Time: 11:02
 */
public class MergeSort {

    public static void main(String[] args) {

        int[] array = {7,3,2,4,1,8,0,9,5,6};
        sort(array, 0, array.length - 1);

        for (int i : array) {
            System.out.print(i + " ");
        }
        System.out.println();

    }

    private static void sort(int[] array, int left, int right) {

        // 递归终止条件
        if (left >= right) {
            return;
        }

        // 均分
        int mid = (left + right) / 2;

        // 排序左部分的
        sort(array, left, mid);

        // 排序右部分的
        sort(array, mid + 1, right);

        // 合并两个有序的数组
        merge(array, left, mid, right);
    }

    private static void merge(int[] array, int left, int mid, int right) {
        // 临时数组
        int[] result = new int[array.length];

        // 左边数组的起始索引
        int l = left;

        // 右边数组的起始索引
        int m = mid + 1;

        // 临时数组的索引
        int index = 0;

        // 同时循环两个数组, 比较两个数组的值, 保存在临时数组中
        while (l <= mid && m <= right) {
            if (array[l] < array[m]) {
                result[index++] = array[l++];
            } else {
                result[index++] = array[m++];
            }
        }

        // 剩余左边数组未比较的元素保存在临沭数组中
        while (l <= mid) {
            result[index++] = array[l++];
        }

        // 剩余右边数组未比较的元素保存在临沭数组中
        while (m <= right) {
            result[index++] = array[m++];
        }

        // 把临时数组中的值还原到原数组中的指定位置
        for (int i = 0; i < index; i++) {
            array[left + i] = result[i];
        }

    }

}

在每次merge的时候都会创建一个数组,这样比较浪费空间,可以在外部定义一个临时数组,然后用入参传进来。

点赞