0

0

JavaScript 中归并排序的实现与常见逻辑错误修复

心靈之曲

心靈之曲

发布时间:2026-03-07 11:05:03

|

292人浏览过

|

来源于php中文网

原创

本文详解归并排序在 javascript 中的标准实现,指出原代码中合并循环条件错误、递归调用缺失及数组分割冗余等问题,并提供可直接运行的修正版本与关键注意事项。

本文详解归并排序在 javascript 中的标准实现,指出原代码中合并循环条件错误、递归调用缺失及数组分割冗余等问题,并提供可直接运行的修正版本与关键注意事项。

归并排序(Merge Sort)是一种经典的分治(Divide and Conquer)排序算法,其核心思想是:递归地将数组二分,直至子数组长度为 1(自然有序),再逐层合并两个已排序的子数组。原问题中的代码看似结构完整,实则存在三处关键缺陷,导致排序完全失效:

? 主要错误分析

  1. mergeTwoSortedArrays 的循环终止条件错误
    原代码使用:

    while (i < A.length && j < B.length && A[i] || B[j])

    该条件逻辑混乱:A[i] || B[j] 会因 0、null、undefined 等 falsy 值提前退出(例如数组含 0 时直接中断),且与索引边界无关。正确条件仅为 i ——仅由索引控制主合并流程。

  2. mergeSort 缺失递归调用
    原函数仅对原始数组做一次简单切分(c 和 d),但未对 c 和 d 分别递归调用 mergeSort,导致子数组从未被排序,直接传入 mergeTwoSortedArrays 的是未排序的两段原始数据,合并结果必然错误。

  3. 数组切分方式低效且易错
    使用 Array.from({ length: ... }, (_, i) => a[...]) 手动构造子数组虽可行,但可简化为更清晰、安全的 slice() 方法,避免索引计算失误。

✅ 修正后的完整实现

以下为修复后、符合算法原理的模块化实现(ES6+ 风格,含注释):

Post AI
Post AI

博客文章AI生成器

下载
const mergeSort = {
  solve: function (A) {
    // 返回新排序数组,不修改原数组
    return this.mergeSortFunction([...A]);
  },

  mergeTwoSortedArrays: function (A, B) {
    let i = 0, j = 0, k = 0;
    const C = [];

    // ✅ 正确主合并:仅依赖索引边界
    while (i < A.length && j < B.length) {
      if (A[i] <= B[j]) { // 使用 <= 保证稳定性(相等时优先取左)
        C[k++] = A[i++];
      } else {
        C[k++] = B[j++];
      }
    }

    // ✅ 补充剩余元素(无需判断 A[i] 或 B[j] 是否为真值)
    while (i < A.length) C[k++] = A[i++];
    while (j < B.length) C[k++] = B[j++];

    return C;
  },

  mergeSortFunction: function (a) {
    const n = a.length;
    if (n <= 1) return a; // 基础情况:长度 ≤1 即有序

    // ✅ 使用 slice() 安全切分,语义清晰
    const mid = Math.floor(n / 2);
    const left = a.slice(0, mid);
    const right = a.slice(mid);

    // ✅ 关键修复:递归排序左右子数组,再合并
    return this.mergeTwoSortedArrays(
      this.mergeSortFunction(left),
      this.mergeSortFunction(right)
    );
  }
};

// ? 使用示例
const input = [38, 27, 43, 3, 9, 82, 10];
console.log("原始数组:", input);
console.log("排序结果:", mergeSort.solve(input));
// 输出: [3, 9, 10, 27, 38, 43, 82]

// ⚠️ 验证原地修改安全:input 未被改变
console.log("原数组未变:", input); // [38, 27, 43, 3, 9, 82, 10]

? 关键注意事项与最佳实践

  • 稳定性保障:合并时使用
  • 空间复杂度意识:每次 slice() 和新建 C 数组均产生额外空间开销,时间复杂度为 O(n log n),空间复杂度为 O(n) —— 这是归并排序的固有特性,不可省略。
  • 避免原数组污染:solve 方法内部使用 [...A] 创建副本,确保函数纯正(pure function),符合函数式编程原则。
  • 调试技巧:若合并结果异常,优先检查 mergeTwoSortedArrays 的循环条件和 mergeSortFunction 是否真正递归;可在递归调用前后添加 console.log(left, right) 快速验证分治过程。

掌握归并排序不仅在于写出代码,更在于理解“分”与“治”的协同逻辑。每一次 slice 是分解的开始,每一次 mergeTwoSortedArrays 是治理的落地——而修复一个循环条件,往往就是打通整个算法脉络的关键钥匙。

立即学习Java免费学习笔记(深入)”;

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

106

2023.07.17

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

197

2023.08.04

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

231

2025.12.24

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

252

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1049

2024.03.01

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

409

2023.09.04

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

953

2023.09.19

console接口是干嘛的
console接口是干嘛的

console接口是一种用于在计算机命令行或浏览器开发工具中输出信息的工具,提供了一种简单的方式来记录和查看应用程序的输出结果和调试信息。本专题为大家提供console接口相关的各种文章、以及下载和课程。

419

2023.08.08

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

23

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 5.8万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.3万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号