归并排序详解

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

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

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

 处理剩余未合并的元素


前言

1. 算法概述

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

分治策略

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

C语言实现

#include <stdio.h>
#include <stdlib.h>
// 合并两个有序数组
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<n1&&j<n2)
    {
        if (L[i] <= R[j]) 
        {
            arr[k] = L[i];
            i++;
        } else 
            {
            arr[k] = R[j];
            j++;
            }
            k++;
    }
     // 拷贝剩余元素(如果有)
    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }
    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
    free(L);
    free(R);
}
void  sort(int arr[],int left,int right)
{
    if(left<right)
    {
        int mid=left+(right-left)/2;
        sort(arr,left,mid)
        sort(arr,mid+1,right);
        merge(arr,left,mid,right);
    }
}
// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
// 测试代码
int main() {
    int arr[] = {38, 27, 43, 3};
    int arr_size = sizeof(arr) / sizeof(arr[0]);
    printf("原始数组: \n");
    printArray(arr, arr_size);
    mergeSort(arr, 0, arr_size - 1);

    printf("排序后数组: \n");
    printArray(arr, arr_size);
    return 0;
}

    初始调用: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)额外空间

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

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值