用 JavaScript 实现归并排序

news2024/11/26 18:29:11

目录

归并排序背后的逻辑

用 JavaScript 实现归并排序

归并排序的效率

总结


归并排序背后的逻辑

归并排序使用分而治之的概念对给定的元素列表进行排序。它将问题分解为较小的子问题,直到它们变得足够简单以至可以直接解决为止。

以下是归并排序的步骤:

  1. 将给定的列表分为两半(如果列表中的元素数为奇数,则使其大致相等)。
  2. 以相同的方式继续划分子数组,直到只剩下单个元素数组。
  3. 从单个元素数组开始,合并子数组,以便对每个合并的子数组进行排序。
  4. 重复第 3 步单元,直到最后得到一个排好序的数组。

以数组 [4, 8, 7, 2, 11, 1, 3] 为例,让我们看一下归并排序是如何工作的:

image.png

用 JavaScript 实现归并排序

首先实现一个将两个已排序子数组合并为一个已排序数组的函数 merge() 。要注意着两个子数组是已经被排好序的,这一点非常重要, merge() 函数只用于其进行合并。

可以通过遍历这两个子数组来实现:

function merge(left, right) {
  let arr = [];
  // 如果任何一个数组为空,就退出循环
  while (left.length && right.length) {
    // 从左右子数组的最小元素中选择较小的元素
    if (left[0] < right[0]) {
      arr.push(left.shift());
    } else {
      arr.push(right.shift());
    }
  }

  // 连接剩余的元素,防止没有把两个数组遍历完整
  return [...arr, ...left, ...right];
}

在这个函数中,通过把两个排好序的子数组(leftright)合并来获得一个排好序的大数组。首先,创建一个空数组。之后在 left 和 right 两个子数组中最小元素中的较小的一个,并将其添加到空数组。我们只需要检查 left 和 right 子数组中的第一个元素,因为它们是已排好序的。

在这个过程中,从子数组中删除了被选择的元素(通过 shift() 函数实现)。继续这个过程,直到其中一个子数组变为空。最后把非空子数组的剩余元素(因为它们已经被排序)插入主数组的最后面。

现在有了合并两个已排序数组的代码,接下来为实现归并排序算法的最终代码。这意味着要继续分割数组,直到最终只包含一个元素的数组为止:

function mergeSort(arr) {
  if (arr.length < 2) {
    return arr;
  }

  const middle = Math.floor(arr.length / 2);
  const left = arr.slice(0, middle);
  const right = arr.slice(middle);

  return merge(mergeSort(left), mergeSort(right));
}

在代码中先确定中点,并用 splice() 函数将数组分为两个子数组。如果元素数量为奇数,则左侧的元素数量会少一个。不断的划分数组,直到剩下单个元素的数组(array.length < 2)。然后用之前实现的 merge() 函数合并子数组。

代码实现后用前面的用例测试一下:

array = [4, 8, 7, 2, 11, 1, 3];
console.log(mergeSort(array));

输出符合预期:

1,2,3,4,7,8,11

归并排序的效率

归并排序的最差时间复杂度为 $O(n\\log n)$,与快速排序的最佳情时间复杂度相同。归并排序是目前最快的排序算法之一。

与快速排序不同,归并排序不是in-place排序算法,这意味着除了输入数组之外,它还会占用额外的空间。这是因为我们使用了辅助数组来存储子数组。归并排序的空间复杂度为 $O(n)$。

归并排序的另一个优点是非常适合多线程,因为每个被划分出的一半都可以单独排序。另一种常见的减少归并排序运行时间的方法是在到达相对较小的子数组时(大约 7 个元素)使用插入排序。这是因为插入排序在处理小型或几乎排好序的数组时表现非常好。

总结

在本文中,我们了解了Merge Sort算法背后的逻辑,并用 JavaScript 实现。它是基本排序算法之一,可以帮助我们更好的了解分治法策略。

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

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

相关文章

C语言第16篇

1.定义如下变量: int n10; 则下列循环的输出结果是_______. while(n>7) { n--; printf("%d\n",n);} A) 10 B) 9 C) 10 D) 9 9 8 9 8 8 7 8 7 7 6 提…

Java 入门指南:注解(Annotation)

注解的基本概念 Java注解&#xff08;Annotation&#xff09;是一种附加在代码中的元数据&#xff0c;用于对程序代码进行说明和补充。同 class 类 和 interface 接口 一样&#xff0c;也属于一种类型。它是在 Java SE 5 中引入的一项新特性&#xff0c;常用于配置、编译和运行…

Linux信号的保存与信号的处理

目录 前言 一、信号保存 1、重谈信号的概念 2、信号在内核中的表示 3、sigset_t 4、信号集操作函数、 • sigset_t相关的接口 • sigpromask • sigpending 二、信号处理 1、再谈地址空间 2、用户态与内核态 • 内核态和用户态的切换 • 用户态切换为内核态的几种…

软件开发的航海之旅:程序员的实用神器

在软件开发的海洋中&#xff0c;程序员们就像勇敢的航海家&#xff0c;驾驭着代码的航船&#xff0c;向着未知的目的地进发。在这个过程中&#xff0c;各种实用的开发工具就如同航海中的指南针&#xff0c;帮助他们导航、加速开发、优化代码质量&#xff0c;并最终抵达成功的彼…

YOLO-V3

一、概述 最大的改进就是网络结构&#xff0c;使其更适合小目标检测特征做的更细致&#xff0c;融入多持续特征图信息来预测不同规格物体先验框更丰富了&#xff0c;3种scale&#xff0c;每种3个规格&#xff0c;一共9种softmax改进&#xff0c;预测多标签任务 先验框&#xf…

dubbo:dubbo+nacos整合springcloud gateway实现网关(三)

文章目录 0. 引言1. 集成gateway网关1.1 实操步骤1.2 dubbo提供者注册到nacos出现两个实例的问题 2. 源码3. 总结 0. 引言 上次我们讲到使用zookeeper作为注册中心搭建dubbo微服务框架&#xff0c;但是我们还缺少一个服务总入口&#xff0c;也就是我们的网关服务。所以今天我们…

小兔鲜首页制作css

一、项目目录 项目名-客户端 xtx-pc 1.images&#xff1a;存放固定使用的图片&#xff0c;例如&#xff1a;logo、样式修饰图 2.uploads:存放非固定图片&#xff0c;例如&#xff1a;商品图、宣传图等需要上传的图片 3.iconfont:字体图标素材 4.css文件&#xff1a; 4.1base.cs…

猫咪除毛除臭大作战!宠物空气净化器帮助铲屎官轻松应对换毛季

最近天气真的好热&#xff0c;可以的话真想呆在空调房一直不出来&#xff0c;人都受不了&#xff0c;何况是一身厚重毛发的猫咪。这不&#xff0c;本该在春季结束的换毛季&#xff0c;延续到了夏天。它就像一个行走的蒲公英&#xff0c;家里到处散落着它的毛发。体臭和便臭在密…

【软件测试·研究向】Major 变异测试工具使用教程

目录 前言 1 安装 1.1 下载解压 1.2 配置环境变量 1.3 入门示例脚本 2 Mutator Plugin 编译器插件 2.1 如何使用插件&#xff1f; 2.2 插件配置选项 2.3 Major 支持的变异算子 2.4 突变体的日志记录 2.5 生成突变体的源代码 3 构建系统集成 4 Major 突变语言 (M…

系统架构设计师:信息系统概述及分类

信息系统是由计算机硬件、网络和通信设备、计算机软件、信息资源、信息用户和规章制度组成的以处理信息流为目的的人机一体化系统。 从技术上可以定义为一系列支持决策和控制的相关要素&#xff0c;这些要素主要包括信息的收集、检索、加工处理和信息服务。除了支持决策、协作…

【Python】动态类型、输入和输出、条件语句

动态类型 程序运行过程中&#xff0c;变量的类型可能会发生改变 a hello print(a) a 10 print(a)#运行结果 hello 10在程序执行过程中&#xff0c;a 的类型刚开始是 int&#xff0c;后面变成了 str C / Java 这样的语言则不允许这样的操作&#xff0c;一个变量定义后类…

Qt第十七章 多线程

文章目录 多线程1. 线程概念的起源2. 三种方式创建线程3. 启动线程前的准备工作4. 启动线程/退出线程5. 操作运行中的线程6. 为每个线程提供独立数据7.子线程不能操作ui解决方案 多线程 1. 线程概念的起源 单核CPU 早期还没有线程的概念&#xff0c;如何保证2个进程同时进行呢…

BaseCTF 高校联合新生赛Week1(web)

目录 HTTP 是什么呀 喵喵喵•&#xfecc;•​编辑 md5绕过欸 A Dark Room upload Aura 酱的礼物 HTTP 是什么呀 url转义&#xff1a; 是将URL中的特殊字符转换为有效的ASCII字符格式的过程&#xff0c;以确保URL的正确解析和传输。这个过程涉及到将非ASCII字符替换为“%h…

【论文阅读】通用的语义-几何表征的机器人操作

文章目录 1. 【2023CoRL】A Universal Semantic-Geometric Representation for Robotic Manipulation针对痛点和贡献引言模型框架思考不足之处 2. Leveraging Locality to Boost Sample Efficiency in Robotic Manipulation摘要和结论引言模型框架实验思考不足之处 1. 【2023Co…

哈希表的查找、插入及删除——217、633、349、128、202、500,290、532、205(五简四中)

217. 存在重复元素&#xff08;简单&#xff09; 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 &#xff0c;返回 true &#xff1b;如果数组中每个元素互不相同&#xff0c;返回 false 。 解法一、哈希 无则加入&#xff0c;有则代表重复&#xff0c;返回true …

Vue自定义横向轮播图

目录 前言代码效果演示详细代码实现思路轮播图实现代码组件使用代码前言 汇总一个最近写出来的效果,最新的设计稿里面要求实现一个轮播图,原本使用的Element-UI提供的轮播图不是很适配,所以选择自定义一个使用。文中附带代码实际效果演示视频。 大致需求就是:一行10个d…

敲桌子游戏

题目 在饭局上&#xff0c;会玩一种敲桌子的游戏&#xff0c;从1报数到100&#xff0c;如果报到个位含有7&#xff0c;或者十位含有7&#xff0c;或者7的倍数的数字&#xff0c;则报数人不能报出该数字&#xff0c;而是敲桌子代替。如果违反了规则&#xff0c;则进行一定的惩罚…

【python】逐步回归(多元线性回归模型中的应用)

文章目录 前言一、逐步回归1. 前进法&#xff08;Forward Selection&#xff09;2. 后退法&#xff08;Backward Elimination&#xff09;3. 逐步回归法&#xff08;Stepwise Regression&#xff09; 二、示例三、代码实现----python 前言 Matlab中逐步回归的实现可以使用 Mat…

流量分析-Windows

目录 介绍步骤 介绍 1、Medusa工具是通过并行登陆暴力破解的方法&#xff0c;尝试获取远程验证服务访问权限&#xff0c;它支持AFP, CVS, FTP, HTTP, IMAP, MS-SQL, MySQL, NCP (NetWare),NNTP, PcAnywhere, POP3, PostgreSQL, rexec, rlogin, rsh, SMB, SMTP(AUTH/VRFY), SNM…

【Windows下Oracle 11G 安装教程】

Windows下 Oracle 11G 安装及配置教程 引言数据库安装安装流程1.运行可执行程序2.取消安装更新配置3.安装及配置数据库4.选择系统的类别5.安装位置及全局数据库6.检查配置及设置情况7.配置对应数据库管理的密码 引言 在网上各种安装教程其实已经很多了&#xff0c;没必要再出这…