说说你对归并排序的理解?如何实现?应用场景?

news2024/11/19 20:23:20

在这里插入图片描述

一、是什么

归并排序(Merge Sort)是建立归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用

将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序

例如对于含有 n 个记录的无序表,首先默认表中每个记录各为一个有序表(只不过表的长度都为 1)

然后进行两两合并,使 n 个有序表变为n/2 个长度为 2 或者 1 的有序表(例如 4 个小有序表合并为 2 个大的有序表)

通过不断地进行两两合并,直到得到一个长度为 n 的有序表为止

例如对无序表{49,38,65,97,76,13,27}进行归并排序分成了分、合两部分:

如下图所示:
在这里插入图片描述
归并合过程中,每次得到的新的子表本身有序,所以最终得到有序表

上述分成两部分,则称为二路归并,如果分成三个部分则称为三路归并,以此类推

二、如何实现

关于归并排序的算法思路如下:

  • 分:把数组分成两半,再递归对子数组进行分操作,直至到一个个单独数字
  • 合:把两个数合成有序数组,再对有序数组进行合并操作,直到全部子数组合成一个完整的数组
  • 合并操作可以新建一个数组,用于存放排序后的数组
  • 比较两个有序数组的头部,较小者出队并且推入到上述新建的数组中
  • 如果两个数组还有值,则重复上述第二步
  • 如果只有一个数组有值,则将该数组的值出队并推入到上述新建的数组中
    在这里插入图片描述
    用代码表示则如下图所示:
function mergeSort(arr) {  // 采用自上而下的递归方法
    const len = arr.length;
    if(len < 2) {
        return arr;
    }
    let middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right)
{
    const result = [];

    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }

    while (left.length)
        result.push(left.shift());

    while (right.length)
        result.push(right.shift());

    return result;
}

上述归并分成了分、合两部分,在处理分过程中递归调用两个分的操作,所花费的时间为2乘T(n/2),合的操作时间复杂度则为O(n),因此可以得到以下公式:

总的执行时间 = 2 × 输入长度为n/2的sort函数的执行时间 + merge函数的执行时间O(n)

当只有一个元素时,T(1) = O(1)

如果对T(n) = 2 * T(n/2) + O(n)进行左右 / n的操作,得到 T(n) / n = (n / 2) * T(n/2) + O(1)

现在令 S(n) = T(n)/n,则S(1) = O(1),然后利用表达式带入得到S(n) = S(n/2) + O(1)

所以可以得到:S(n) = S(n/2) + O(1) = S(n/4) + O(2) = S(n/8) + O(3) = S(n/2^k) + O(k) = S(1) + O(logn) = O(logn)

综上可得,T(n) = n * log(n) = nlogn

关于归并排序的稳定性,在进行合并过程,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也不会交换,由此可见归并排序是稳定的排序算法

三、应用场景

在外排序中通常使用排序-归并的策略,外排序是指处理超过内存限度的数据的排序算法,通常将中间结果放在读写较慢的外存储器,如下分成两个阶段:

  • 排序阶段:读入能够放进内存中的数据量,将其排序输出到临时文件,一次进行,将带排序数据组织为多个有序的临时文件
  • 归并阶段:将这些临时文件组合为大的有序文件

例如,使用100m内存对900m的数据进行排序,过程如下:

  • 读入100m数据内存,用常规方式排序
  • 将排序后的数据写入磁盘
  • 重复前两个步骤,得到9个100m的临时文件
  • 将100m的内存划分为10份,将9份为输入缓冲区,第10份为输出缓冲区
  • 进行九路归并排序,将结果输出到缓冲区
  • 若输出缓冲区满,将数据写到目标文件,清空缓冲区
  • 若缓冲区空,读入相应文件的下一份数据

参考文献

  • https://baike.baidu.com/item/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F/1639015
  • https://chowdera.com/2021/09/20210920201630258d.html#_127
  • https://juejin.cn/post/6844904007899561998

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
在这里插入图片描述

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

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

相关文章

C++项目在Linux下编译动态库

一、说明 最近在Windows下开发了一个C线程池项目&#xff0c;准备移植到Linux下&#xff0c;并且编译成动态库进行使用。现将具体过程在此记录。 二、准备 1、项目文件 我的项目文件如下&#xff0c;其中除main.cpp是测试文件之外&#xff0c;其他都是线程池项目相关的 将C…

为什么光电测径仪质量更稳定可靠?

光电测径仪与激光扫描式测径仪都是目前常用的外径自动化测量设备&#xff0c;他们能实现的功能相同&#xff0c;但为什么说光电测径仪更稳定可靠&#xff0c;下面一起来看一下。 光电测径仪测量原理 测头部件是测径仪的核心部件&#xff0c;它的作用是将被测物在CCD芯片上清晰…

基于SpringBoot的合家云社区物业管理平台 - 权限管理模块开发

合家云社区物业管理平台 4.权限管理模块开发 4.1 权限管理概述 4.1.1 权限管理的意义 后台管理系统中&#xff0c;通常需要控制不同的登录用户可以操作的内容。权限管理用于管理系统资源&#xff0c;分配用户菜单、资源权限&#xff0c;以及验证用户是否有访问资源权限。 …

【软件测试】采用等价类划分法设计测试用例

例题1 请采用等价类划分法设计测试用例。 考虑软件 app, 它有两个输入变量 , 分别是 name 和 age, 其中 ,name 是至多包含 20 个字母字符的非空字符串 ,age 是整数型变量 ,0 ≤ age ≤ 120 。当输入给 name 的字符串的长度超过 20时 ,name 取前 20 个字符作为 name 的值 ; 如果…

Hotcoin Academy 市场洞察-2024年4月15日-21日

加密货币市场表现 BTC ETF在本周出现净流出&#xff0c;大盘有较大跌幅&#xff0c;BTC一度跌破60000美金&#xff0c;ETH一度跌破2800美金&#xff0c;整体以横盘为主&#xff0c;行情在周末有略微回升趋势。BTC市占率创21年4月来新高&#xff0c;目前市值1.28万亿&#xff0c…

导出瑞芯微(Rockchip)芯片的设备树(Device Tree)

要导出瑞芯微&#xff08;Rockchip&#xff09;芯片的设备树&#xff08;Device Tree&#xff09;&#xff0c;可以使用设备树编译器&#xff08;DTC&#xff0c;Device Tree Compiler&#xff09;。通常&#xff0c;会有一个设备树的源文件&#xff08;.dts&#xff09;&#…

网络编程-libuv介绍

官网 https://libuv.org/ 概要 libuv是一个强大的跨平台异步I/O库&#xff0c;主要用于构建高性能、可扩展的网络应用程序。它最初是为Node.js开发的&#xff0c;用于处理Node.js的异步I/O操作&#xff0c;但随着时间的推移&#xff0c;它也被广泛应用于其他系统&#xff0…

#1 Numpy Pandas

Numpy & Pandas 2.1 numpy属性2.2 numpy的创建array2.3 numpy的基础运算 调入头文件 import numpy as np2.1 numpy属性 #生成一个array数组 array np.array([[1, 2, 3],[2, 3, 4]])#也可以这样 dtype表示array的元素类型 np.array([1, 2, 3], dtype np.int64) #array维…

AQ6370C YOKOGAWA 横河 光谱分析仪 简述

YOKOGAWA AQ6370C是一款高性能的光谱分析仪&#xff0c;具有世界一流的光学性能。它的波长范围为600至1700nm&#xff0c;能够提供高波长精度0.01nm和高波长分辨率0.02nm。此外&#xff0c;AQ6370C具备大动态范围78dB&#xff08;典型值&#xff09;和宽功率量程20~-90dBm&…

安装VCenter 7 对硬件资源的需求

安装VMware vCenter Server 7.x 对硬件资源的需求主要包括以下方面&#xff1a; 服务器硬件&#xff1a; 处理器&#xff1a;64位 x86架构&#xff0c;推荐采用多核CPU以支持高并发管理和运行多个虚拟机。具体数量取决于vCenter Server将管理的虚拟机规模及复杂度。内存&#x…

excel 按照姓名日期年月分组求和

excel 需要按照 姓名 日期的年份进行金额求和统计&#xff0c;采用sumifs 进行统计 注意&#xff1a;sumifs 不支持 合并列拆分计算&#xff0c;合并列只会计算一个值 表格数据大概如下&#xff1a;(sheet) ABC姓名日期金额A2023/01/01500A2023/01/151500B2023/01/01200B202…

Pycharm 函数无法跳转,设置import的路径

想要跳转时报错 可以看到import都报错了&#xff0c;未解析的引用 xxxxx之类的 解决办法&#xff1a; 这个一般是import的路径问题&#xff0c; 这个根目录必填&#xff0c;按照自己的目录填写&#xff0c;如果不填&#xff0c;虽然不会报错&#xff0c;但是也是无法跳转的…

CUDA的开发技术难点

CUDA的开发技术难点不仅包括对并行计算模型的理解&#xff0c;还涉及到内存管理、线程同步、性能优化等多个方面。开发者需要不断学习和实践&#xff0c;才能熟练掌握CUDA编程。CUDA的开发技术难点主要集中在以下几个方面。北京木奇移动技术有限公司&#xff0c;专业的软件外包…

RS®FSH 手持式频谱分析仪

手持式频谱分析仪 R&SFSH -彰显移动性能r- 一体化 灵敏度出色 9 kHz 至 20 GHz 该一体化手持式分析仪非常适合现场的常规测量任务 R&SFSH 手持式频谱分析仪还可以用作网络分析仪、电缆与天线分析仪、干扰捕获分析仪和功率计。这款多功能分析仪可实现简单高效的现…

书生·浦语大模型开源体系(四)笔记

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

【计算机系统结构】指令级高度并行的超级计算机

&#x1f4dd;本文介绍 本文将以三种处理机&#xff1a;超标量处理机&#xff0c;超长指令字处理机&#xff0c;超流水线处理机来简要介绍指令高度并行的超级计算机 &#x1f44b;作者简介&#xff1a;一个正在积极探索的本科生 &#x1f4f1;联系方式&#xff1a;943641266(QQ…

数据安全:什么是数据风险评估?等保合规为什么是企业必需品

作为一项保护措施&#xff0c;组织应定期执行数据风险评估&#xff0c;以审查和保护敏感信息。但什么是数据风险评估以及执行数据风险评估的优秀方法是什么&#xff1f;等保合规为什么是企业必需品 数据风险评估是我国《数据安全法》明确要求的内容&#xff0c;我们知道在传统的…

linux使用docker 安装mysql redis

linux安装docker https://hub-stage.docker.com/ 前往这里搜索容器来部署。每个容器都有独立的运行环境。 具体安装教程 https://docs.docker.com/engine/install/centos/#install-using-the-repository 检查是否安装成功&#xff1a; sudo docker --version 配置国内镜像加速…

【零基础入门TypeScript】环境

目录 定义环境 句法 例子 环境声明是告诉 TypeScript 编译器实际源代码存在于其他地方的一种方式。当您使用大量第三方js库&#xff08;如 jquery/angularjs/nodejs&#xff09;时&#xff0c;您无法在 TypeScript 中重写它。对于 TypeScript 程序员来说&#xff0c;在使用这…

18.AVL树的模拟实现

前面对map/multimap/set/multiset进行了简单的介绍&#xff0c;在其文档介绍中发现&#xff0c;这几个容器有个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的&#xff0c;但是二叉搜索树有其自身的缺陷&#xff0c;假如往树中插入的元素有序或者接近有序&#xff0c;二…