Java 归并排序法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/afei__/article/details/82950292

一、原理简介

归并排序又称合并排序,即针对两个已经排序好的数组,将其合并为一个排序数组。归并过程中,依次比较两个数组中的元素,将较小值(假设为升序排序)放入新数组中,最终遍历完两个数组后完成排序。

归并排序是一种速度较快的排序方法。

 

二、时间复杂度

当我们合并 两个已排序的数组,只需要遍历一遍即可,其时间复杂度为 O(n)。

当我们对一个 无序数组 使用归并排序法进行排序,我们可以使用分治法将数组进行对半划分,递归解决。由于进行二分的时间复杂度为 O(lg n),单次合并(即合并两个已排序的数组)操作时间复杂度为 O(n),所以综合时间复杂度为 O(n * lg n)。

 

三、合并两个已排序的数组

这种情况时间复杂度为 O(n)。因为我们只需要遍历一遍。

1. 两个数组合并为一个

public class Main {
 
    public static void main(String[] args) {
        // 前提:arr1 和 arr2 都是已排序的
        int[] arr1 = new int[] { 3, 15, 23, 76, 100 };
        int[] arr2 = new int[] { 1, 16, 18, 55, 66 };
        int[] arr = mergeSort(arr1, arr2);
        printArray(arr);
    }
 
    public static int[] mergeSort(int[] arr1, int[] arr2) {
        int[] arr = new int[arr1.length + arr2.length];
        int i = 0; // arr1当前index
        int j = 0; // arr2当前index
        int k = 0; // arr当前index
        while (i < arr1.length && j < arr2.length) {
            if (arr1[i] < arr2[j]) {
                arr[k++] = arr1[i++];
            } else {
                arr[k++] = arr2[j++];
            }
        }
        if (i != arr1.length) {
            System.arraycopy(arr1, i, arr, k, arr1.length - i);
        } else {
            System.arraycopy(arr2, j, arr, k, arr2.length - j);
        }
        return arr;
    }
 
    public static void printArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
 
}

2. 一个数组,左右两段是已排序的

和上例类似,只是 arr1 和 arr2 可以视为这一个数组的左右两部分。

public class Main {
 
    public static void main(String[] args) {
        // 前提:arr 的左半部分[0, 5)和右半部分[5, 10)均已排序。区间均为左闭右开
        int[] arr = new int[] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
        mergeSort(arr, 0, 5, 10);
        printArray(arr);
    }
 
    /**
     * 归并排序
     * @param arr 目标数组,满足 p < q≤ r,且区间 [p...q) 和 [q...r) 均已排好序
     * @param p 起始位置
     * @param q 中间位置
     * @param r 结束位置
     */
    public static void mergeSort(int[] arr, int start, int pivot, int end) {
        int[] temp = new int[end - start];
        int i = start;
        int j = pivot;
        int k = 0;
        while (i < pivot && j < end) {
            if (arr[i] < arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }
        if (i != pivot) {
            System.arraycopy(arr, i, temp, k, pivot - i);
        } else {
            System.arraycopy(arr, j, temp, k, end - j);
        }
        System.arraycopy(temp, 0, arr, start, temp.length);
    }
 
    public static void printArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
 
}

四、无序数组排序

这种情况时间复杂度为 O(n * lg n)。

我们需要对数组折半划分,直至其足够小时(例如数组长度为 1),可视为左右两个数组是已排序的(长度为 1 的数组可以视为已排序的),然后分别执行上面的合并操作。递归执行下去,最终完成整个数组的排序。

public class Main {
 
    public static void main(String[] args) {
        int[] arr = new int[] { 2, 3, 8, 6, 1 };
        mergeSort(arr, 0, arr.length);
        printArray(arr);
    }
 
    public static void mergeSort(int[] arr, int start, int end) {
        int length = end - start;
        if (length > 1) { // 长度大于1才需要排序
            int mid = (start + end) / 2;
            mergeSort(arr, start, mid); // sort left
            mergeSort(arr, mid, end); // sort right
            merge(arr, start, mid, end); // merge left and right
        }
    }
 
    public static void merge(int[] arr, int start, int mid, int end) {
        // check input
        if (arr == null || start < 0 || end > arr.length) {
            return;
        }
        int[] temp = new int[end - start];
        int i = start;
        int j = mid;
        int k = 0;
        while (i < mid && j < end) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }
        if (i != mid) {
            System.arraycopy(arr, i, temp, k, mid - i);
        } 
        if (j != end){
            System.arraycopy(arr, j, temp, k, end - j);
        }
        System.arraycopy(temp, 0, arr, start, temp.length);
    }
 
    public static void printArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
 
}

猜你喜欢

转载自blog.csdn.net/afei__/article/details/82950292