图解归并排序

归并排序的流程如下

第一步:对数列每次都进行切分,直到不能再切分
这里写图片描述

每次都对数列进行切分分组,直到每组的元素都只有一个,学过递归的话很容易想到这种重复性的动作用递归很容易实现。对于8个数的数列,切分三次直到第四层就不能再切分了。

第二步:进行归并

对于上述的数列,当每组的元素都是一个,也就是说每组的都是有序的了,递归返回,返回到倒数第二层。此时可对每组元素进行归并

这里写图片描述

再进行归并

这里写图片描述

可以看到归并将每组的数排成有序的了,最后我们将最后两组数再进行归并即可。

这里写图片描述

此时,数列有序,归并结束

编程思路

对于每次把数列按半切分分组,对分好的组进行归并这个流程可以用递归实现:

//归并过程
    public static void merge(int arr[],int l,int mid,int r){
        //归并排序辅助数组
        int T[] = new int[r-l+1];
        //T[0]到T[r-l]保存arr[l]到arr[r]的值
        for(int i = l; i <= r; i++){
            T[i-l] = arr[i];
        }
        //使用i指向分组1的第一个数的位置,j指向分组2的第一个数的索引
        int i = l,j = mid+1;
        //需要归并的数组位置是[l,r]
        for(int k = l ; k <= r; k++){

            if(i > mid){    //归并后,分组2还有元素,依次覆盖到原数组对应处
                arr[k] = T[j-l];
                j++;
            }else if(j > r){    //归并后,分组1还有元素,依次覆盖到原数组对应处
                arr[k] = T[i-l];
                i++;
            }else if(T[i-l] < T[j-l]){ //将分组中小的数覆盖到原数组对应处
                arr[k] = T[i-l];
                i++;
            }else if(T[i-l] >= T[j-l]){
                arr[k] = T[j-l];
                j++;
            }
        }

    }

T[]是辅助数组,用来存放两个需要进行归并的分组。在归并时,每次将两组中的最小的那个数依次放到原数组。

这个过程如下所示:
这里写图片描述

优化

public static void merge_sort(int arr[],int l,int r){
        if(l >= r)
            return;
        /**对于数不是很多的情况下,可以使用插入排序代替归并来提高效率
         * if(r - l <= 10){
         *      插入排序;
         *      return;
         * }
        */
        int mid = (l+r) / 2;
        merge_sort(arr,l,mid);
        merge_sort(arr,mid+1,r);
        //优化,归并时左边的最后一个数已经是小于右边第一个数时,可以不用归并了
        if(arr[mid] > arr[mid+1]){
            merge(arr,l,mid,r);
        }
    }
### 归并排序递归过程 归并排序的核心思想基于分治法(Divide and Conquer),它通过递归的方式将数组分割成更小的部分,直到每个部分只包含单个元素。随后再逐步合并这些子序列,最终形成一个完整的有序列表。 #### 1. **分解阶段** 在分解阶段,原始数组被不断划分为两半,直至每组只剩下一个元素为止。这一过程可以通过递归来实现。每次调用函数时,都会将当前数组的一半传递给下一层递归[^1]。 ```python def merge_sort(arr): if len(arr) <= 1: return arr mid = len(arr) // 2 left_half = merge_sort(arr[:mid]) # 左侧递归划分 right_half = merge_sort(arr[mid:]) # 右侧递归划分 return merge(left_half, right_half) ``` #### 2. **合并阶段** 当所有的子数组都被拆分到最小单位后,程序进入合并阶段。在此过程中,两个相邻的小数组会被逐一比较,并按顺序组合成更大的有序数组。此操作由 `merge` 函数完成: ```python def merge(left, right): sorted_array = [] i = j = 0 while i < len(left) and j < len(right): # 合并左、右两侧数据 if left[i] < right[j]: sorted_array.append(left[i]) i += 1 else: sorted_array.append(right[j]) j += 1 # 将剩余未处理的数据加入结果集 sorted_array.extend(left[i:]) sorted_array.extend(right[j:]) return sorted_array ``` --- ### 图解归并排序的工作流程 假设有一个待排序数组 `[8, 4, 23, 42, 16, 15]`,以下是其递归执行的过程图解: #### 初始状态: 输入数组为: `[8, 4, 23, 42, 16, 15]` #### 分解阶段: 1. 数组被一分为二: `[8, 4, 23]`, `[42, 16, 15]` 2. 继续细分左侧子数组: `[8], [4, 23]` → 进一步细分为 `[4], [23]` 3. 对右侧子数组继续细分: `[42], [16, 15]` → 进一步细分为 `[16], [15]` 此时,所有子数组都已被细化至单一元素的状态。 #### 合并阶段: 1. 开始自底向上地合并已排序的子数组: - 合并 `[4]` 和 `[23]` 得到 `[4, 23]` - 合并 `[16]` 和 `[15]` 得到 `[15, 16]` 2. 接着合并更高层次的结果: - 合并 `[8]` 和 `[4, 23]` 得到 `[4, 8, 23]` - 合并 `[42]` 和 `[15, 16]` 得到 `[15, 16, 42]` 3. 最终合并顶层结果: - 合并 `[4, 8, 23]` 和 `[15, 16, 42]` 得到 `[4, 8, 15, 16, 23, 42]` --- ### 总结 整个归并排序可以看作是一个先分裂后聚合的过程,在每一次递归中都将原问题缩小一半规模,从而达到高效排序的目的。时间复杂度稳定为 O(n log n),空间复杂度则取决于额外存储的需求,通常为 O(n)[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值