算法——归并排序(基本思想、java实现、实现图解)

server/2025/1/18 4:54:36/
我是一个计算机专业研0的学生卡蒙Camel🐫🐫🐫(刚保研)
记录每天学习过程(主要学习Java、python、人工智能),总结知识点(内容来自:自我总结+网上借鉴)
希望大家能一起发现问题和补充,也欢迎讨论👏👏👏

文章目录

  • 归并排序
    • 介绍
    • Java代码实现
    • 算法分析
    • 实现图解🖌️
    • 和快速排序对比(面试)

归并排序

介绍

归并排序(Merge Sort)是一种基于分治法的排序算法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

  1. 基本思想:它的工作原理是将数组递归地分成两个子数组,对每个子数组分别进行排序,然后将已排序的子数组合并成一个完整的有序数组。归并排序的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn) ,这使得它对于大型数据集非常有效。

  2. 步骤:归并排序是一个递归算法

  3. 分解:将未排序的数组以中点为中心分为两个子数组。

  4. 解决:递归地对这两个子数组进行归并排序。

  5. 合并:将两个已经排序好的子数组合并成一个单一的有序数组。

Java代码实现

java">import java.util.Arrays;public class MergeSort {// 主函数,用于启动归并排序public static void mergeSort(int[] array) {if (array.length < 2) {return;}int mid = array.length / 2;int[] left = Arrays.copyOfRange(array, 0, mid);int[] right = Arrays.copyOfRange(array, mid, array.length);mergeSort(left); // 递归排序左半部分mergeSort(right); // 递归排序右半部分// 排序完后,左右两边都是有序的merge(array, left, right); // 合并左右两部分}// 合并两个已排序的子数组private static void merge(int[] result, int[] left, int[] right) {int i = 0, j = 0, k = 0;// 1. 比较两个数组的大小,将小的放入合并数组肿while (i < left.length && j < right.length) {if (left[i] <= right[j]) {result[k++] = left[i++];} else {result[k++] = right[j++];}}// 2. 比较完后,将其中一边剩余的数组全部添加到合并数组中while (i < left.length) {result[k++] = left[i++];}while (j < right.length) {result[k++] = right[j++];}}// 测试方法public static void main(String[] args) {int[] array = {38, 27, 43, 3, 9, 82, 10};System.out.println("原始数组: " + Arrays.toString(array));mergeSort(array);System.out.println("排序后的数组: " + Arrays.toString(array));}
}

算法分析

  • 稳定性:稳定

  • 时间复杂度

  • 最佳: O ( n l o g n ) O(nlogn) O(nlogn)

  • 最差: O ( n l o g n ) O(nlogn) O(nlogn)

  • 平均: O ( n l o g n ) O(nlogn) O(nlogn)

  • 空间复杂度 O ( n ) O(n) O(n)

实现图解🖌️

img

  1. 根据上图可知,使用递归方法(递归出口是当数组长度为1的时候),然后逐渐左右两个数组合并,直到合并完成(先排序再合并)。

  2. 合并过程:将两个已经有序的数组合并成一个有序数组

    2.1 初始化指针

    • i:指向left数组的起始位置。

    • j:指向right数组的起始位置。

    • k:指向result数组的起始位置。

    2.2 比较与合并

    • 比较left[i]right[j],将较小的那个复制到result[k]中,并向前移动相应数组的指针(i++j++),同时更新k++以指向下一个待填充的位置。

    • 重复上述步骤直到其中一个子数组被完全遍历。

    2.3 处理剩余元素

    • 如果leftright中的任意一个还有剩余元素,则直接将这些元素复制到result数组中,因为它们已经是有序的。

    • 注意,由于我们总是从两个子数组中选择较小的元素,所以当一个子数组被耗尽时,另一个子数组剩下的所有元素都比之前放入result的所有元素要大,因此可以直接添加到result的末尾。

    2.4 完成合并

    • 当所有元素都被正确放置到result数组后,合并过程结束。

和快速排序对比(面试)

特性归并排序 (Merge Sort)快速排序 (Quick Sort)
时间复杂度O(n log n)平均情况:O(n log n) 最坏情况:O(n²)
空间复杂度O(n) - 需要额外空间用于合并操作O(log n) - 递归栈空间 最坏情况:O(n)
稳定性稳定排序算法不稳定排序算法
适应性对任何输入数据分布都能保持一致性能对几乎已排序的数据集特别有效但对有序数据可能退化到最坏情况
实现难度实现较为直观,代码结构清晰实现相对复杂,尤其是优化措施如随机基准选择等
应用场景外部排序问题、大文件排序、需要维持元素相对顺序的应用内存中的小到中等规模数据集的内部排序
原地排序否 - 需要额外数组存储是 - 在理想情况下只需要少量额外空间
分区策略分而治之,将数组分成两半选择一个基准元素,然后根据基准划分数组
递归深度每次递归调用都减少一半,通常为 logn取决于基准选择;最坏情况下可能是 n

http://www.ppmy.cn/server/159263.html

相关文章

DNS介绍与部署-Day 01

1. 什么是DNS DNS&#xff08;Domain Name System&#xff09;域名系统&#xff0c;是一种采用客户端/服务器机制&#xff0c;负责实现计算机名称与IP地址转换的系统。DNS作为一种重要的网络服务&#xff0c;既是Internet工作的基础&#xff0c;同时在企业内部网络中也得到了广…

前后端分离开发心得

前后端分离开发是一种软件开发模式&#xff0c;将前端和后端的开发分离开来&#xff0c;使得前端和后端可以独立开发、测试和部署。具体来说&#xff1a; • 前端&#xff1a;负责展示数据和用户交互&#xff0c;使用 HTML、CSS、JavaScript 等技术实现用户界面和交互逻辑&…

向量数据库如何助力Text2SQL处理高基数类别数据

01. 导语 Agent工作流和 LLMs &#xff08;大语言模型&#xff09;的出现&#xff0c;让我们能够以自然语言交互的模式执行复杂的SQL查询&#xff0c;并彻底改变Text2SQL系统的运行方式。其典型代表是如何处理High-Cardinality Categorical Data &#xff08;高基数类别数据&am…

SVM支持向量机

目录 算法原理 数学基础 向量内积&#xff08;向量点乘&#xff09; 范数 对偶问题 拉格朗日乘子法 ​线性可分与线性不可分 线性可分 线性不可分 超平面 超平面的定义 超平面的作用 如何寻找最优的超平面 损失函数求解 软间隔 鲁棒性 核函数 算法优缺点 优点…

运输层安全协议SSL

安全套接字层 SSL (Secure Socket Layer) SSL 作用在端系统应用层的 HTTP 和运输层之间&#xff0c;在 TCP 之上建立起一个安全通道&#xff0c;为通过 TCP 传输的应用层数据提供安全保障。 应用层使用 SSL 最多的就是 HTTP&#xff0c;但 SSL 并非仅用于 HTTP&#xff0c;而是…

Coconut:基于连续潜在空间推理,提升大语言模型推理能力的新方法

Coconut&#xff08;连续思维链&#xff09;提出了一种新的大语言模型推理范式&#xff0c;该范式在潜在空间中进行运算&#xff0c;利用模型隐藏层生成的连续思维状态取代传统的基于文本的推理方式。系统将这些状态以输入嵌入的形式反馈至模型&#xff0c;通过广度优先搜索方法…

macos 一直报错 XXX 将对你的电脑造成伤害。你应该将它移到废纸篓

Docker 将对你的电脑造成伤害。你应该将它移到废纸篓 今天碰到一个神奇的问题&#xff0c;Docker 忽然运行不了了&#xff0c;然后将 Docker 卸载重装&#xff0c;接着就出现了这个问题&#xff0c;电脑一直弹框这个错误&#xff0c;将 Docker 卸载也不行&#xff0c;重启之后就…

深入理解观察者模式 —— Qt信号槽机制的实现

观察者模式是一种行为型设计模式&#xff0c;允许一个对象&#xff08;被观察者&#xff09;状态发生变化时通知一组依赖它的对象&#xff08;观察者&#xff09;&#xff0c;从而实现对象之间的解耦。在这篇文章中&#xff0c;我们将探讨如何用 C 和 Python 实现观察者模式&am…