js 实现归并排序算法

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

递归法求解

javascript 复制代码
const mergeSort = (arr) => {
    const n = arr.length
    if (n <= 1) {
        return arr
    }
    let mid = Math.floor(n / 2)
    const arr1 = arr.slice(0, mid)
    const arr2 = arr.slice(mid, n)
    return merge(mergeSort(arr1), mergeSort(arr2), n)
}

const merge = (arr1, arr2, n) => {
    const mergeArr = new Array(n)
    let idx = 0
    let idx1 = 0
    let idx2 = 0
    while(idx1 < arr1.length && idx2 < arr2.length) {
        if (arr1[idx1] < arr2[idx2]) {
            mergeArr[idx] = arr1[idx1]
            idx1 += 1
        } else {
            mergeArr[idx] = arr2[idx2]
            idx2 += 1
        }
        idx += 1
    }
    if (idx1 < arr1.length) {
        while(idx1 < arr1.length) {
            mergeArr[idx] = arr1[idx1]
            idx1 += 1
            idx += 1
        }
    } else {
        while(idx2 < arr2.length) {
            mergeArr[idx] = arr2[idx2]
            idx2 += 1
            idx += 1
        }
    }
    return mergeArr
}

const arr = [1100,200,500,1600,25,13,685,23651,0,12,35,478,66,5,3,9,8,456,58,68,95,25,12,45,65,8,78,95,68,321,456,122,258,951,864,57,85,95,96,93,92,94,98,25,26,28,29,68,65,62,67,789,752,751,745,6859,3,20,359,215,687,592]
const newarr = mergeSort(arr)
console.log(newarr)

递归法需要新建很多新数组占用存储空间,数据大时比较占内存。

非递归法

gap从小往大逐渐增加,c++的实现方法如下

cpp 复制代码
// 非递归 处理越界版本
void _MergeSort(int* a, int L, int R, int* tmp, int n) {
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = begin1 + gap - 1;
			int begin2 = end1 + 1, end2 = begin2 + gap - 1;

			// 处理越界的逻辑
			if (end1 >= n || begin2 >= n) break;
			if(end2 >= n) end2 = n - 1;


			int j = begin1;
			while (begin1 <= end1 && begin2 <= end2) {
				if (a[begin1] < a[begin2]) {
					tmp[j++] = a[begin1++];
				}
				else if (a[begin1] >= a[begin2]) { // 还有一种相等的情况,随便加在一个地方就行
					tmp[j++] = a[begin2++];
				}
			}

			// 当区间没走完,就把剩下的拷贝进数组
			while (begin1 <= end1) {
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2) {
				tmp[j++] = a[begin2++];
			}
			memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1)); // 注意不能直接用 begin1 ,begin1 已经加加变化过了
		}
		gap *= 2;
	}
}
相关推荐
变量未定义~23 分钟前
最小生成树1(Prim模板)、最小生成树2(kruskal模板)、最近公共祖先(模板)
算法
这就是佬们吗26 分钟前
Python入门⑤-异常处理、文件操作与实战项目
开发语言·数据库·python·算法·pycharm
LONGZETECH34 分钟前
新能源汽车充电设备装配与调试仿真教学软件 技术架构与核心实现解析
大数据·算法·3d·unity·架构·汽车
自学小白菜36 分钟前
关于提升机器学习算法做预测回归任务精度的方法分享
算法·机器学习·回归·提升精度
学废了wuwu44 分钟前
从入门到实战:深入浅出模型压缩三大核心——剪枝、彩票假设与知识蒸馏
人工智能·算法·剪枝
小肝一下1 小时前
3. 单链表
c语言·数据结构·c++·算法·leetcode·链表·dijkstra
劈星斩月1 小时前
监督学习算法 之 决策树
学习·算法·决策树
学计算机的计算基1 小时前
操作系统内存管理全解:虚拟内存、页表、COW、malloc、OOM一篇搞定
java·笔记·算法
tachibana21 小时前
hot100 前 K 个高频元素(347)
java·数据结构·算法·leetcode
To_OC9 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode