归并排序算法

归并排序(Merge Sort)是一种基于分治法的排序算法,时间复杂度为O(n log n),空间复杂度为O(n)。它通过递归地将数组分成两个子数组,分别排序,然后合并成有序数组。

归并排序算法原理:

  1. 分(Divide):将待排序数组递归地分成两半,直到每个子数组只有一个元素,单个元素天然有序。
  2. 治(Conquer):对每个子数组进行排序。
  3. 合(Merge):将两个已排序的子数组合并成一个有序数组。

算法步骤:

  1. 如果数组长度小于2,无需排序,直接返回。
  2. 找到数组的中点,将数组分成左右两部分。
  3. 递归地对左半部分和右半部分进行归并排序。
  4. 合并两个有序子数组:使用两个临时数组存储左右子数组,比较两个临时数组的元素,依次将较小的元素放入原数组,如果有剩余元素,将剩余元素复制到原数组。

Java 代码实现:

public void mergeSort(int[] arr, int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }
}

private void merge(int[] arr, int left, int mid, int right) {
    int n1 = mid - left + 1;
    int n2 = right - mid;
    int[] leftArr = new int[n1];
    int[] rightArr = new int[n2];

    // 填充临时数组
    // 将原数组的左子数组(arr[left..mid])复制到 leftArr。
    for (int i = 0; i < n1; i++) {
        leftArr[i] = arr[left + i];
    }
    // 将原数组的右子数组(arr[mid+1..right])复制到 rightArr。
    for (int j = 0; j < n2; j++) {
        rightArr[j] = arr[mid + 1 + j];
    }

    // 合并
    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (leftArr[i] <= rightArr[j]) { // 使用<=保持稳定性,相同元素的相对顺序不会改变。
            arr[k++] = leftArr[i++];
        } else {
            arr[k++] = rightArr[j++];
        }
    }
    while (i < n1) {
        arr[k++] = leftArr[i++];
    }
    while (j < n2) {
        arr[k++] = rightArr[j++];
    }
}

时间复杂度:每次递归都会二分数组,递归深度为 log n , 每次合并操作需要O(n),总共log n层,所以总时间为O(n log n)。

空间复杂度:递归是二分的,最大递归深度为 log ⁡ n \log n logn,因此调用栈的空间占用为 O ( log ⁡ n ) O(\log n) O(logn)。在 merge 方法中,创建了两个临时数组,总临时数组大小为 n 1 + n 2 = r i g h t − l e f t + 1 n1 + n2 = right − left + 1 n1+n2=rightleft+1,在最顶层递归(合并整个数组时),right - left + 1 = n,因此临时数组的总大小最大为 O ( n ) O(n) O(n),虽然每一层递归的 merge 都会创建临时数组,但这些数组在 merge 方法结束后会被垃圾回收,且递归是分阶段执行的(先完成左子树递归,再右子树,再合并),因此不会同时存在多个大数组。总体来看,临时数组的空间占用在任何时刻不会超过 O ( n ) O(n) O(n)。其他变量空间占用为O(1),常数级别。因此总空间复杂度为: O ( n ) + O ( l o g n ) + O ( 1 ) = O ( n ) O(n)+O(logn)+O(1)=O(n) O(n)+O(logn)+O(1)=O(n),由于 O ( n ) O(n) O(n) 是主导项,归并排序的空间复杂度为 O ( n ) O(n) O(n)

归并排序是稳定的排序算法,适用于大数据量,时间复杂度不受数据分布影响,始终为O(n log n),适合链表排序,因为只有遍历操作,没有随机插入操作。但是因为存在递归,在极大数据量的情况下可能导致栈溢出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值