归并排序:优雅的分治排序算法(C语言实现)

一、算法思想

归并排序的核心思想是 分治法(Divide and Conquer)

  1. 分解:将待排序数组递归地分成两半

  2. 解决:对子数组进行排序

  3. 合并:将两个有序子数组合并成一个有序数组

二、算法特性

  • 时间复杂度:O(nlogn)(最优/平均/最差情况)

  • 空间复杂度:O(n)(需要额外存储空间)

  • 稳定性:稳定(相同元素相对位置不变)

三、C语言实现

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

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

// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    int arr_size = sizeof(arr) / sizeof(arr[0]);
    
    printf("原始数组: \n");
    printArray(arr, arr_size);
    
    mergeSort(arr, 0, arr_size - 1);
    
    printf("\n排序后数组: \n");
    printArray(arr, arr_size);
    return 0;
}

四、关键代码解析

  1. merge函数

    • 创建临时数组存储左右子数组

    • 使用双指针法合并两个有序数组

    • 保证排序稳定性(<= 判断)

  2. mergeSort函数

    • 递归终止条件:left >= right

    • 计算中点:mid = left + (right - left)/2(避免整数溢出)

    • 先递归排序,后合并结果

五、执行过程示例

复制代码
原始数组: [12, 11, 13, 5, 6, 7]

分解过程:
[12, 11, 13] 和 [5, 6, 7]
→ [12] [11,13] 和 [5] [6,7]
→ 排序合并:[11,13] → [11,12,13]
→ 排序合并:[5,6,7]
→ 最终合并:[5,6,7,11,12,13]

六、性能分析

情况 时间复杂度 空间复杂度
最优 O(nlogn) O(n)
平均 O(nlogn) O(n)
最差 O(nlogn) O(n)
辅助空间 O(n)

:虽然归并排序需要额外空间,但其稳定性和可预测的性能使其成为:

  • 大数据量排序的优选

  • 外部排序的基础(如海量数据排序)

  • 链表排序的最佳选择

七、优化方向

  1. 小数组优化:当子数组小于阈值时改用插入排序

  2. 免复制合并:交替使用原始数组和辅助数组

  3. 迭代法实现:消除递归调用栈

八、总结

归并排序凭借其 稳定 的时间复杂度和 稳定排序 的特性,在以下场景表现优异:

  1. 需要稳定排序的场合(如数据库排序)

  2. 链表排序(仅需修改指针,空间复杂度降为O(1))

  3. 大数据量排序(优于O(n²)算法)

相关推荐
智驱力人工智能8 小时前
工厂智慧设备检测:多模态算法提升工业安全阈值
人工智能·算法·安全·边缘计算·智慧工厂·智能巡航·工厂设备检测
2501_9247314711 小时前
城市路口识别准确率↑31%!陌讯时空建模算法在交通拥堵识别中的突破
人工智能·算法·目标检测·计算机视觉·目标跟踪
熬了夜的程序员11 小时前
【华为机试】208. 实现 Trie (前缀树)
数据结构·算法·华为od·华为
小O的算法实验室13 小时前
2024年ESWA SCI1区TOP,自适应种群分配和变异选择差分进化算法iDE-APAMS,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
不吃洋葱.14 小时前
左子树之和
算法
金融小师妹15 小时前
基于AI量化模型的比特币周期重构:传统四年规律是否被算法因子打破?
大数据·人工智能·算法
数据智能老司机16 小时前
图算法趣味学——最短路径
数据结构·算法·云计算
快去睡觉~16 小时前
力扣109:有序链表转换二叉搜索树
算法·leetcode·链表
gopher_looklook16 小时前
Go并发实战:singleflight 源码解读与二次封装
数据结构·后端·go
是Dream呀16 小时前
YOLOv8深度解析:从架构革新到应用实践
人工智能·算法