Fork me on GitHub

JavaScript实现归并排序

JavaScript实现归并排序

参考文章

归并排序就这么简单---文章通俗易懂,加深理解

过程描述

归并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

代码实现

根据参考文章,仅做语言上的修改变更,后文有代码简化版

/**
 * 归并排序
 * @param {Array} arrays 
 * @param {Number} L 数组第一个元素
 * @param {Number} R 数组最后一个元素
 */
function mergeSort(arrays, l, r) {
    if (l === r) {
        return;
    } else {
        // 取中间的数,进行拆分
        const m = Math.floor((l + r) / 2);

        //左边不断进行拆分
        mergeSort(arrays, l, m);
        //右边不断进行拆分
        mergeSort(arrays, m + 1, r);
        //合并
        merge(arrays, l, m + 1, r);

    }
}


/**
 * 合并数组
 * @param {Array} arrays 
 * @param {Number} l 数组第一个元素
 * @param {Number} m 数组分割元素
 * @param {Number} r 数组最后一个元素
 */
function merge(arrays, l, m, r) {
    let leftArr = new Array(m - l),//左边数组大小
        rightArr = new Array(r - m + 1);//右边数组大小

    //往数组中填充数据
    for (let i = l; i < m; i++) {
        leftArr[i - l] = arrays[i];
    }
    for (let i = m; i <= r; i++) {
        rightArr[i - m] = arrays[i];
    }

    let i = 0, j = 0, k = l;

    //比较这两个数组的值,哪个小就往数组上放
    while (i < leftArr.length && j < rightArr.length) {
        if (leftArr[i] < rightArr[j]) {
            arrays[k] = leftArr[i];
            k++;
            i++;
        } else {
            arrays[k] = rightArr[j];
            k++;
            j++;
        }
    }

    //如果左边的数组没读完,那么把剩余的都直接填充到后面
    while (i < leftArr.length) {
        arrays[k] = leftArr[i];
        k++;
        i++;
    }

    // //如果右边的数组没读完,那么把剩余的直接填充都后面
    while (j < rightArr.length) {
        arrays[k] = rightArr[j];
        k++;
        j++;
    }
}

//测试demo
let originArr = [9, 2, 5, 1, 3, 2, 9, 5, 2, 1, 8];
mergeSort(originArr, 0, originArr.length - 1);
console.log(originArr);//[1, 1, 2, 2, 2, 3, 5, 5, 8, 9, 9]

简化代码的实现

/**
 * 归并排序
 * @param {Array} arrays 
 * @param {Number} L 数组第一个元素
 * @param {Number} R 数组最后一个元素
 */
function mergeSort(arrays, l, r) {
    if (l === r) {
        return;
    } else {
        // 取中间的数,进行拆分
        const m = Math.floor((l + r) / 2);
        //左边不断进行拆分
        mergeSort(arrays, l, m);
        //右边不断进行拆分
        mergeSort(arrays, m + 1, r);
        //合并
        merge(arrays, l, m + 1, r);
    }
}


/**
 * 合并数组
 * @param {Array} arrays 
 * @param {Number} l 数组第一个元素
 * @param {Number} m 数组分割元素
 * @param {Number} r 数组最后一个元素
 */
function merge(arrays, l, m, r) {
    let leftArr = arrays.slice(l, m),//左边数组
        rightArr = arrays.slice(m, r + 1);//右边数组

    let i = 0, j = 0, k = l;

    //比较这两个数组的值,哪个小就往数组上放
    while (i < leftArr.length && j < rightArr.length) {
        arrays[k++] = leftArr[i] < rightArr[j] ? leftArr[i++] : rightArr[j++];
    }

    //如果左边的数组没读完,那么把剩余的都直接填充到后面
    while (i < leftArr.length) {
        arrays[k++] = leftArr[i++];
    }

    //如果右边的数组没读完,那么把剩余的直接填充都后面
    while (j < rightArr.length) {
        arrays[k++] = rightArr[j++];
    }
}
let originArr = [9, 2, 5, 1, 3, 2, 9, 5, 2, 1, 8];
mergeSort(originArr, 0, originArr.length - 1);
console.log(originArr);

posted @   粥里有勺糖  阅读(288)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示