归并排序

本秂侑毒 提交于 2020-02-10 17:44:43

归并排序

  1. 将给定的包含n个元素的局部数组“分割”为俩个局部数组,每个数组包含 n/2 个元素。
  2. 对两个局部数组分别进行归并排序。
  3. 通过归并把两个已经排序的局部数组“整合”成一个数组。

举例:以 a = [9,6,7,2,5,1,8,4,2]进行归并排序

在这里插入图片描述
注:红色数字代表执行顺序。

代码:

import java.util.Arrays;

public class MergeSort {
    public static void mergeSort(int[] arr, int left, int right) {
        //直到分割到单个元素,停止分割
        if(left+1<right) {
            int mid = (left+right) / 2;
            //分割为2个数组
            mergeSort(arr, left, mid);
            mergeSort(arr, mid, right);
            //合并2个数组
            merge(arr, left, mid, right);  
        }        
    }

    public static void merge(int[] arr, int left, int mid, int right) {
        //申请额外空间存储排序结果
        int[] result = new int[right - left];
        int i = 0, p1 = left, p2 = mid;
        // 比较分割的数组的元素,哪个小,把那个元素填入result中
        while(p1 < mid && p2 < right) {
            result[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }
        //循环结束,把剩余的元素依次加入到result中
        // 以下两个while只有一个会执行
        while(p1 < mid) {
            result[i++] = arr[p1++];
        }
        while(p2 < right) {
            result[i++] = arr[p2++];
        }
        // 把最终的排序的结果复制给原数组
        for(i = 0; i < result.length; i++) {
            arr[left + i] = result[i];
        }
    }
    
    public static void main(String[] args) {
        int[] a = {9,6,7,2,5,1,8,4,2};
        mergeSort(a, 0, a.length);
        System.out.println(Arrays.toString(a));
    }
}

结果:[1, 2, 2, 4, 5, 6, 7, 8, 9]

总结:

  1. 一般来说,n 个数据大致会分为 log2 n 层。由于每层执行归并的总复杂度为 O(n), 所以归并排序的时间复杂度为 O(nlogn)
  2. 归并排序包含不相邻元素之间的比较,但并不会直接交换。在合并两个已排序数组时,如果遇到了相同元素,只要保证前半部分数组优先于后半部分数组,相同元素的顺序就不会颠倒。因此归并排序属于稳定的排序算法。
  3. 归并排序在处理过程中,需要临时占用一部分内存空间。所以归并排序的空间复杂度为O(n)。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!