java - 归并排序

一、什么是归并排序

归并排序是一种常见的排序算法,也是一种分治策略的典型应用。该算法的基本思想是将待排序的序列分成若干个子序列,然后递归地对这些子序列进行排序,最终将排好序的子序列合并成一个有序序列。

具体来说,归并排序的过程可以分为两个阶段。

第一个阶段是分解,即将原序列分成若干个长度相等的子序列,每个子序列再分成若干个长度相等的子序列,直到无法分解为止。

第二个阶段是合并,即将已排好序的子序列合并成一个有序序列。

二、代码实现

递归:

java 复制代码
 public static void mergeSort(int[] nums,int left,int right){
        if(left >= right){
            return ;
        }
        int mid = (left+right)/2;
        mergeSort(nums,left,mid);
        mergeSort(nums,mid+1,right);
        merge(nums,left,mid,right);
    }
    public static void merge(int[] nums,int left,int mid,int right){
        // 左子数组区间 [left, mid], 右子数组区间 [mid+1, right]
        // 创建一个临时数组 tmp ,用于存放合并后的结果
        int[] tmp = new int[right-left+1];
        int k = 0;
        int s1 = left;
        int s2 = mid+1;
        // 当左右子数组都还有元素时,比较并将较小的元素复制到临时数组中
        while(s1 <= mid && s2 <= right){
            if(nums[s1] <= nums[s2]){
                tmp[k++] = nums[s1++];
            }else{
                tmp[k++] = nums[s2++];
            }
        }
        // 将左子数组和右子数组的剩余元素复制到临时数组中
        while (s1 <= mid){
            tmp[k++] = nums[s1++];
        }
        while (s2 <= right){
            tmp[k++] = nums[s2++];
        }
         // 将临时数组 tmp 中的元素复制回原数组 nums 的对应区间
        for (int i = 0; i < tmp.length; i++) {
            nums[i+left] = tmp[i];
        }
    }

非递归:

java 复制代码
public  static void mergeSort(int[] nums){
        //模拟递归的效果
        int gap = 1;
        while(gap < nums.length){
            for (int i = 0; i < nums.length; i += gap * 2) {
                int left = i;
                int mid = left + gap -1;
                if(mid >= nums.length){
                    mid  = nums.length -1;
                }
                int right = mid + gap;
                if(right >= nums.length){
                    right  = nums.length -1;
                }
                merge(nums,left,mid,right);
            }
            gap *= 2;
        }
    }
 public static void merge(int[] nums,int left,int mid,int right){
        int[] tmp = new int[right-left+1];
        int k = 0;
        int s1 = left;
        int s2 = mid+1;
        while(s1 <= mid && s2 <= right){
            if(nums[s1] <= nums[s2]){
                tmp[k++] = nums[s1++];
            }else{
                tmp[k++] = nums[s2++];
            }
        }
        while (s1 <= mid){
            tmp[k++] = nums[s1++];
        }
        while (s2 <= right){
            tmp[k++] = nums[s2++];
        }
        for (int i = 0; i < tmp.length; i++) {
            nums[i+left] = tmp[i];
        }
    }

三、算法特性

时间复杂度: O(n ^ log n),划分产生高度为 log ⁡n 的递归树,每层合并的总操作数量为 n ,因此总体时间复杂度为 O(n ^ log⁡ n) 。

空间复杂度:O(n),递归深度为 log⁡ n ,使用 O(log⁡ n) 大小的栈帧空间。合并操作需要借助辅助数组实现,使用 O(n) 大小的额外空间。

稳定排序:在合并过程中,相等元素的次序保持不变。

相关推荐
AbandonForce3 分钟前
从入门到入土:二分查找算法
数据结构·算法
L_09076 分钟前
【C++】数据结构之哈希表(散列表)
数据结构·c++·散列表
仰泳之鹅8 分钟前
【C语言】动态内存管理
c语言·数据结构·算法
心中有国也有家11 分钟前
CANN 学习新范式:cann-learning-hub 如何让昇腾入门不再「劝退」
人工智能·经验分享·笔记·学习·算法
LB211213 分钟前
C++通讯录课设(西安石油大学)
开发语言·c++·算法
AI算法沐枫13 分钟前
机器学习知识点:正则化
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
手写码匠13 分钟前
从零实现一个轻量级向量搜索引擎(Python 版)
人工智能·深度学习·算法·aigc
_Evan_Yao16 分钟前
数据结构太难了?用画图的方式理解链表和栈和树和图
数据结构·学习·链表
学习中.........20 分钟前
多目标优化:遗传算法详解
人工智能·算法·机器学习
心中有国也有家1 小时前
hixl:昇腾分布式推理的「快递专线」
人工智能·经验分享·笔记·分布式·学习·算法