当前位置: 首页 > ai >正文

归并排序详解

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

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

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

 处理剩余未合并的元素


前言

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)额外空间

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

    http://www.xdnf.cn/news/14760.html

    相关文章:

  1. 【网工|知识升华版|实验】4 DHCP原理及应用
  2. 数据结构20250620_数据结构考试
  3. 南方大暴雨及洪水数据分析与可视化
  4. 【Linux】不小心又创建了一个root权限账户,怎么将它删除?!
  5. Rust实现FasterR-CNN目标检测全流程
  6. 什么是端到端自动驾驶
  7. [HDLBits] Cs450/timer
  8. Spring MVC详解
  9. windows系统下将Docker Desktop安装到除了C盘的其它盘中
  10. 力扣 hot100 Day32
  11. 毫米波雷达 – 深度学习
  12. 腾讯 iOA 零信任产品:安全远程访问的革新者
  13. 【仿muduo库实现并发服务器】Channel模块
  14. Wireshark TS | 诡异的光猫网络问题
  15. rocketmq 之 阿里云转本地部署实践总结
  16. MySQL MVCC 详解
  17. Linux基本命令篇 —— grep命令
  18. jQuery UI 安装使用教程
  19. 设置linux静态IP
  20. 苹果AR/VR头显路线图曝光,微美全息推进AI/AR智能眼镜新品开启视觉体验篇章
  21. 《UE5_C++多人TPS完整教程》学习笔记40 ——《P41 装备(武器)姿势(Equipped Pose)》
  22. 为什么js是单线程?
  23. 应用场景全解析:飞算 JavaAI 的实战舞台
  24. 使用vue开发浏览器chrome插件教程,及之间的消息通信
  25. Rust征服字节跳动:高并发服务器实战
  26. HarmonyOS应用开发高级认证知识点梳理 (三)状态管理V2装饰器核心规则
  27. 端到端 pluto 之数据预处理
  28. js代码09
  29. 飞算JavaAI—AI编程助手 | 编程领域的‘高科技指南针’,精准导航开发!
  30. 边缘人工智能与医疗AI融合发展路径:技术融合与应用前景(下)