(十五)排序算法-归并排序

news2025/2/25 4:24:39

1 基本介绍

1.1 概述

归并排序(Merge Sort)是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。

将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。

1.2 算法详解

下面通过图来了解归并排序算法的思想:
在这里插入图片描述
上图中,分和合并的过程特别像递归,都是按照一定的终止条件一直执行下去。所以这就暗示了归并排序是可以通过递归的思想来编写的。

归并排序的特点:

  • 归并排序是稳定的,通过上面的图解过程就能看出来。
  • 归并排序需要消耗大量的内存空间。这个内存空间是对比冒泡排序之类的排序算法而言的,因为它们的内存空间都是只存在于常量级别的,但是归并排序却是需要消耗线性级别的内存空间,所以才会使用大量这个形容词。消耗的内存空间就是等同于待排序序列的长度。即O(n)的复杂度。

算法图解:
在这里插入图片描述
动画展示
在这里插入图片描述

2 代码实现

代码实现:

/**
 * 归并排序
 */
public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 7, 2, 2, 2, 1, 3, 6, 2};
        int[] temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
        System.out.println(Arrays.toString(arr));

    }


    // 分+合方法
    public static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            // 中间索引
            int mid = (left + right) / 2;
            // 向左递归进行分解
            mergeSort(arr, left, mid, temp);
            // 向右递归进行分解
            mergeSort(arr, mid + 1, right, temp);
            // 合并
            merge(arr, left, mid, right, temp);
        }
    }


    /**
     * 合并方法
     *
     * @param arr   排序的原始数组
     * @param left  左边有序序列的初始索引
     * @param mid   中间索引
     * @param right 右边索引
     * @param temp  做中转的数组
     */
    public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        // 初始化 i,左边有序序列的初始索引
        int i = left;
        // 初始化 j,右边有序序列的初始索引
        int j = mid + 1;
        // 指向 temp 数组的当前索引
        int t = 0;

        // 先把左右两边(有序)的数据,按照规则填充到 temp 数组,直到左右两边的有序序列有一边处理完毕为止
        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                // 如果发现左边的有序序列的当前元素,小于等于右边的有序序列的当前元素
                // 即将左边的当前元素,拷贝到 temp 数组
                // 然后 t++ i++
                temp[t] = arr[i];
                t++;
                i++;
            } else {
                // 反之,将右边有序列表的当前元素,填充到 temp 数组
                temp[t] = arr[j];
                t++;
                j++;
            }
        }

        // 把有剩余数据的一边的数据依次全部填充到 temp 中
        while (i <= mid) {
            // 左边的有序序列还有剩余的元素
            temp[t] = arr[i];
            t++;
            i++;
        }
        while (j <= right) {
            // 右边的有序序列还有剩余的元素
            temp[t] = arr[j];
            t++;
            j++;
        }

        // 将 temp 数组重新拷贝到 arr
        t = 0;
        int tempLeft = left;
        while (tempLeft <= right) {
            arr[tempLeft] = temp[t];
            t++;
            tempLeft++;
        }
    }

}

3 复杂度分析

  • 时间复杂度
    从上面的算法中能明显看出来,没有使用for循环,而是通过递归的方式来解决循环问题的。所以更加的高效。
    这个执行的层数为2 * log N,并且每层操作的元素是N个,所以我们的时间复杂度即为2 * N * log N,但是常数可以忽略不计,所以时间复杂度就控制在了O(Nlog N),对比之前算法的时间复杂度O(NN),可以看到时间复杂度明显降低很多,并且这个时间复杂度不仅仅只是适用于平均情况,针对最坏的情况,同样也能适用。

  • 空间复杂度
    整个排序的过程中需要增加一个等同于排序序列的长度的空间来存储为二次排序之后的序列,所以需要的空间复杂度就是线性级别的O(n),这个复杂度对比之前的几种排序算法,可以看得出来的确是较为大了一点,但是也可以明显看出来整个的时间复杂度明显降低了很多,这就是一种跟明显通过牺牲空间换取时间的方法。

  • 稳定性:稳定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/427607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为浮动路由和BFD配置

拓扑图 电脑配置 pc1:192.168.10.1/24 pc2:192.168.20.1/24 AR1路由器配置 配置4个接口的地址 ge0/0/0:192.168.10.254/24 ge0/0/1:192.168.20.254/24 ge0/0/2:12.1.1.1/30 ge4/0/0:13.1.1.1/30 <Huawei>system-view Enter system view, return user view with CtrlZ…

机器学习笔记之正则化(五)Dropout

机器学习笔记之正则化——Dropout引言引子&#xff1a;题目描述(正则化相关)正确答案&#xff1a;ABCD\mathcal A\mathcal B\mathcal C\mathcal DABCD题目解析回顾&#xff1a;集成学习方法&#xff1a;Bagging\text{Bagging}BaggingDropout\text{Dropout}Dropout方法深度神经网…

黑马程序员微服务技术栈教程 - 1. SpringCloud 微服务治理

教程链接&#xff1a;https://www.bilibili.com/video/BV1LQ4y127n4 黑马的资料下载链接&#xff1a;https://pan.baidu.com/s/1zRmwSvSvoDkWh0-MynwERA&pwd1234 目录认识微服务单体架构分布式架构微服务微服务结构微服务技术对比SpringCloud总结 &#x1f380;服务拆分及远…

刷题day54:柱形图中最大矩形

题意描述&#xff1a; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 暴力方法&#xff1a; class Solution { public:int largestRectangleArea(ve…

软考第四章 局域网与城域网

局域网与城域网 传统局域网&#xff08;LAN&#xff09;是分组广播式网络&#xff0c;这是与分组交换式的广域网的主要区别。广播技术中&#xff0c;所有工作站都连接到共享的传输介质上&#xff0c;共享信道的分配技术是局域网的核心技术&#xff0c;而这一技术又与网络的拓扑…

故障分析 | 从一则错误日志到 MySQL 认证机制与 bug 的深入分析

作者&#xff1a;李锡超 一个爱笑的江苏苏宁银行 数据库工程师&#xff0c;主要负责数据库日常运维、自动化建设、DMP平台运维。擅长MySQL、Python、Oracle&#xff0c;爱好骑行、研究技术。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得…

Redis的MoreKey和BigKey问题

文章目录1、MoreKey案例2、BigKey案例1、MoreKey案例 大批量往Redis里面插入200w测试数据key 在Linux Bash下面执行&#xff0c;插入200w数据 for((i1;i<200*10000;i)); do echo "set k$i v$i">>/root/redisTest.txt;done;使用命令 tail -10 redisTest.t…

Android四大组件之 Activity的启动过程源码解析

前言 Activity是Android中一个很重要的概念&#xff0c;堪称四大组件之首&#xff0c;关于Activity有很多内容&#xff0c;比如生命周期和启动Flags&#xff0c;这二者想要说清楚&#xff0c;恐怕又要写两篇长文&#xff0c;更何况分析它们的源码呢。不过本文的侧重点不是它们…

小黑向携程进攻啦1:跟紧沛奇老师的携程步伐

为什么要学 异步非阻塞、asynciotornado、fastapi、django 3.x asgi、aiohttp都在异步->提升功能 如何讲解&#xff1f; 协程asyncio模块进行异步编程实战案例 1.协程 协程不是计算机提供&#xff0c;程序员人为创造出来的。协程&#xff0c;又称微线程&#xff0c;是一…

共聚焦显微镜——光伏产业制造智能化测量新技术

我国智能光伏应用持续升级&#xff0c;产业各环节产量又创新高。根据光伏行业规范公告企业信息和行业协会预测的数据来看&#xff0c;全国多晶硅、组件产量同比增长均超过60%&#xff0c;晶硅电池产品出口同比增长超过156%。 以共聚焦显微测量技术为原理、应用于材料生产领域的…

STM32的SRAM

文章目录SRAM的概念XM8A51216介绍特点连接线原理框图硬件连接图SRAM的配置使能 FSMC 时钟&#xff0c;并配置 FSMC 相关的 IO 及其时钟使能初始化FSMC&#xff0c;设置FSMC BANK1区域3使能 BANK1 区域 3FSMC读写代码SRAM的概念 SRAM的介绍 STM32F407ZGT6自带了 192K字节的 SRA…

[助人为乐]层次分析法

朋友论文需要用到层次分析法。于是回顾了一下。 相关资料推荐 层次分析法(AHP) 层次分析法&#xff08;AHP&#xff09;详细版本 用人话讲明白AHP层次分析法&#xff08;非常详细原理简单工具实现&#xff09; 层次分析法的流程图 构建层次结构模型(目标-准则-方案层) 深入…

认证服务---OAuth2.0基本介绍,微博登录整合到实际项目中【下篇】

前言 上一篇简单介绍了它的基本使用&#xff0c;这一篇就粗略说明一下如何在项目中实际应用 1、核心代码 1.1 认证微服务 当你进行了授权之后&#xff0c;跳转到一个新的地址。这个地址应该是你访问接口的地址。在这个接口中完成相应的access_token获取&#xff0c;以及调用…

docker-compose容器编排使用详解+示例

文章目录一、docker-compose概述1、产生的背景2、核心概念3、使用的三个步骤4、常用命令二、下载安装1、官方文档2、下载3、卸载三、使用compose1、前置知识&#xff0c;将一个springboot项目打包为镜像2、编写docker-compose.yml文件3、启动docker-compose4、停止一、docker-c…

[Linux]进程控制精讲,简单实现一个shell

目录 前言 进程创建 fork函数初识 写时拷贝 fork常见用法 fork调用失败的原因 进程终止 进程退出场景 进程退出码 查看进程退出码 退出码的含义 进程常见退出方法 exit VS _exit exit函数 _exit函数 二者的区别 return退出 进程等待 进程等待必要性 进程等待…

【Java文件操作】手把手教你拿捏IO 流

哈喽&#xff0c;大家好~我是保护小周ღ&#xff0c;本期为大家带来的是 Java 文件操作&#xff0c;理解文件的概念以及&#xff0c;常用的操作文件的类和方法&#xff0c;FileInputStream 类 和 FileOutputStream , PrintWriter and Scnner, Reader and Wirter 确定不来看看…

Python机器学习:集成学习

前两天看了SVM、逻辑回归、KNN、决策树、贝叶斯分类这几个很成熟的机器学习方法&#xff0c;但是&#xff0c;今天不看方法了&#xff0c;来看一种思想&#xff1a;集成学习&#xff1a; 先来看一下集成学习的基本原理&#xff1a;通过融合多个模型&#xff0c;从不同的角度降…

3.4 随机变量的相互独立性

学习目标&#xff1a; 要学习二维随机变量的相互独立性&#xff0c;我会按照以下步骤进行&#xff1a; 学习独立性的概念&#xff1a;在概率论中&#xff0c;两个事件A和B是相互独立的&#xff0c;当且仅当它们的概率乘积等于它们的联合概率&#xff0c;即P(A∩B)P(A)P(B)。将…

【Java EE】-网络编程(二) Socket(套接字) + Udp版本客户端服务器 +Tcp版本客户端服务器

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【JavaEE】 主要内容&#xff1a;传输层协议对应Socket编程&#xff0c;DatagramSocket&#xff0c;DatagramPacket&#xff0c;Udp版本的客户端和服务器&#xff0c;UdpEchoSeve…

大力出奇迹——GPT系列论文学习(GPT,GPT2,GPT3,InstructGPT)

目录说在前面1.GPT1.1 引言1.2 训练范式1.2.1 无监督预训练1.2.2 有监督微调1.3 实验2. GPT22.1 引言2.2 模型结构2.3 训练范式2.4 实验3.GPT33.1引言3.2 模型结构3.3 训练范式3.4 实验3.4.1数据集3.5 局限性4. InstructGPT4.1 引言4.2 方法4.2.1 数据收集4.2.2 各部分模型4.3 …