归并排序详解

创建两个临时数组存储待合并的子数组     

 使用双指针法依次比较两个子数组的元素          

将较小的元素放入原数组的对应位置       

 处理剩余未合并的元素


前言

1. 算法概述

归并排序是一种采用分治法(Divide and Conquer)策略的排序算法,由约翰·冯·诺伊曼在1945年提出。它的核心思想是将一个大问题分解成若干个小问题,递归解决小问题后,再将结果合并起来。

分治策略

分解:将当前区间一分为二  解决:递归地对两个子区间进行排序 合并:将两个已排序的子区间合并成一个有序区间

C语言实现

#include 
#include 
// 合并两个有序数组
void merge(int arr[], int left, int mid, int right) {
    int i, j, k;
    int n1 = mid - left + 1;  // 左子数组长度
    int n2 = right - mid;      // 右子数组长度
    // 创建临时数组
    int *L = (int *)malloc(n1 * sizeof(int));
    int *R = (int *)malloc(n2 * sizeof(int));
    // 拷贝数据到临时数组
    for (i = 0; i < n1; i++)
        L[i] = arr[left + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[mid + 1 + j];
    i=0,j=0;
     k=left;
    while(i

    初始调用:mergeSort(arr, 0, 3)mid = 1递归左:mergeSort(arr, 0, 1)mid = 0递归左:mergeSort(arr, 0, 0) → 直接返回递归右:mergeSort(arr, 1, 1) → 直接返回merge([38,27], 0, 0, 1) → 变为 [27, 38]递归右:mergeSort(arr, 2, 3)mid = 2递归左:mergeSort(arr, 2, 2) → 直接返回递归右:mergeSort(arr, 3, 3) → 直接返回merge([43,3], 2, 2, 3) → 变为 [3, 43]merge([27,38,3,43], 0, 1, 3) → 最终 [3, 27, 38, 43]

    可能的优化

     小数组优化:当子数组较小时(如 <15个元素),改用插入排序    避免重复分配内存:预先分配临时缓冲区   自底向上实现:使用迭代代替递归减少调用开销

    与其他排序算法比较

    特性 归并排序 快速排序 堆排序
    时间复杂度 O(n log n) O(n log n) O(n log n)
    空间复杂度 O(n) O(log n) O(1)
    稳定性 稳定 不稳定 不稳定
    适用性 通用 通用 通用
    最佳场景 大数据/外部排序 内存中小数据集 内存受限环境

    为什么归并排序需要额外空间?
     因为合并两个有序数组时需要临时存储空间,无法在原数组上直接操作而不破坏数据

     如何判断归并排序是否完成?
     当所有子数组都已被分解为单个元素并重新合并后,排序即完成。

     归并排序在实际应用中的限制是什么?
    主要限制是需要O(n)的额外空间,这在内存受限的环境中可能成为问题。


    总结

    核心机制:递归分解数组至单元素后,通过有序合并逐步构建有序序列     三步骤:分界计算→双路递归→有序合并     边界处理:mid = left + (right-left)/2防溢出   空间换时间:需O(n)额外空间

    该算法完美诠释了分治思想,在效率与稳定性间取得平衡,成为处理大规模数据的经典选择

    你可能感兴趣的:(归并排序详解)