归并排序 Merge Sort

news/2024/5/17 17:12:28 标签: 排序算法, 算法, 归并排序

在这里插入图片描述

归并排序的基本思想是什么?

归并排序采用分治法(Divide and Conquer),将待排序的数组分成若干个子数组再对子数组进行排序,最后将已排序的子数组合并成一个大的有序数组。

下面是归并排序的基本步骤:

  • 分解-Divider:将待排序的数组按照中间位置分成两个子数组,再将每个子数组按照相同的方式分解,直到子数组无法分解为止,即长度为 0 或 1。
  • 合并-Conquer:将两个已排序的子数组合并成一个有序的数组,然后将所有的子数组进行合并,直到最后得到完整的有序数组。

归并排序的 JavaScript 实现?

使用自上而下的递归实现:

// 归并函数
function merge(left, right) {
    var result = [];
    let i = 0,
        j = 0,
        k = 0;
    while (i < left.length && j < right.length) {
		// 判断大小
        (left[i] <= right[j] && (result[k++] = left[i++]))
        ||(result[k++]=right[j++]);
    }
    // 添加剩余元素
    while (i < left.length) {
        result[k++] = left[i++];
    }
    // console.log(left, right, result);
    while (j < right.length) {
        result[k++] = right[j++];
    }
    return result;
}
// 分解函数
function mergeSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }
    // JavaScript 中除法运算会得到小数,因此使用 Math.floor 向下取整
    var middle = Math.floor(arr.length / 2);
    var left = arr.slice(0, middle);
    var right = arr.slice(middle);
    // 递归
    return merge(mergeSort(left), mergeSort(right));
}

输出:

[ 5 ] [ 4 ] [ 4, 5 ]
[ 2 ] [ 1 ] [ 1, 2 ]
[ 3 ] [ 1, 2 ] [ 1, 2, 3 ]
[ 4, 5 ] [ 1, 2, 3 ] [ 1, 2, 3, 4, 5 ]
[ 1, 2, 3, 4, 5 ]

使用自下而上的迭代实现:

// arr 是原数组,start 为起点,mid 是中间点,end 是终点
function merge(arr, start, mid, end) {
    var result = [];
    let i = start,
        j = mid,
        k = 0;
    // 开始归并
    while (i < mid && j < end) {
        (arr[i] <= arr[j] && (result[k++] = arr[i++])) 
        || (result[k++] = arr[j++]);
    }
    // 归并剩余元素
    while (i < mid) {
        result[k++] = arr[i++];
    }
    while (j < end) {
        result[k++] = arr[j++];
    }
    //console.log(start, mid, end, result);
    // 将结果更新到原数组
    for (let i = start; i < end; i++) {
        arr[i] = result[i - start];
    }
}
function mergeSort(arr) {
	// seg为一个分组大小
    for (let seg = 1; seg < arr.length; seg *= 2) {
        for (let start = 0; start < arr.length; start += seg * 2) {
            merge(arr,
                start,
                Math.min(start + seg, arr.length),
                Math.min(start + seg * 2, arr.length));
        }
    }
}
let arr = [5, 4, 3, 2, 1];
mergeSort(arr);
console.log(arr);

输出:

0 1 2 [ 4, 5 ]
2 3 4 [ 2, 3 ]
4 5 5 [ 1 ]
0 2 4 [ 2, 3, 4, 5 ]
4 5 5 [ 1 ]
0 4 5 [ 1, 2, 3, 4, 5 ]
[ 1, 2, 3, 4, 5 ]

观察到,使用递归和使用迭代实现的归并排序的排序过程是由一定区别的,递归是从两边归并,迭代是从前往后归并。

就记住 mergeSort 函数的作用是 divide,将数组不停从中间分割,然后调用 merge 函数进行 conquer——归并。


归并排序算法复杂度是?

归并排序的数组分解需要 O(logn) 次操作,而每一次分解都需要进行 O(n) 时间的合并,所以总的时间复杂度是 O(nlogn)。

归并操作需要 O(n) 的额外空间,如果使用递归的话还有栈空间消耗,为 O(logn)。总的空间复杂度还是 O(n)。


归并排序是否稳定?

稳定的排序指的是原序列中两个相等的元素在排序后先后顺序不变。

稳不稳定看归并排序的归并操作:

while (i < left.length && j < right.length) {
	(left[i] <= right[j] && (result[k++] = left[i++]))
	||(result[k++]=right[j++]);
}
  1. left[i] <= right[j],result[k++] = left[i++]
  2. left[i] > right[j],result[k++]=right[j++]

遇到元素相等时,优先处理了左边元素,这保证稳定性。


归并排序的优缺点

归并排序适用于大规模数据的排序,且具有稳定性,但是归并排序需要较大的临时空间来存储排序过程中的数组。


参考资料


http://www.niftyadmin.cn/n/5007764.html

相关文章

CSS文字居中对齐学习

CSS使用text-align属性设置文字对齐方式&#xff1b;text-align:center&#xff0c;这样就设置了文字居中对齐&#xff1b; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>css 水平居中</title><style>.box …

Python实现SSA智能麻雀搜索算法优化XGBoost分类模型(XGBClassifier算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 麻雀搜索算法(Sparrow Search Algorithm, SSA)是一种新型的群智能优化算法&#xff0c;在2020年提出&a…

QuantLib学习笔记——看看几何布朗运动有没有股票走势的感觉

⭐️ 小鹿在乱撞 小伙伴们肯定看过股票的走势&#xff0c;真是上蹿下跳啊&#xff0c;最近小编学了一丢丢关于随机过程和QuantLib的知识&#xff0c;想利用随机过程生成一个类似股票价格走势的图&#xff0c;安排&#xff01;&#xff01;&#xff01; ⭐️ 随机过程 随机过程…

数字 IC 设计职位经典笔/面试题(四)

共100道经典笔试、面试题目&#xff08;文末可全领&#xff09; 画出 CMOS 电路的晶体管级电路图,实现 YA*BC(DE).&#xff1f; 画出 YABC 的 CMOS 电路图&#xff0c;画出 YABCD 的 CMOS 电路图。 利用与非门和或非门实现 YABC(DE)((AB’)(CD)’(CE)’)’ 三个两输入与非门&a…

FasterNet(PConv)paper笔记(CVPR2023)

论文&#xff1a;Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks 先熟悉两个概念&#xff1a;FLOPS和FLOPs&#xff08;s一个大写一个小写&#xff09; FLOPS: FLoating point Operations Per Second的缩写&#xff0c;即每秒浮点运算次数&#xff0c;或…

【HTML专栏3】!DOCTYPE、lang、字符集的作用

本文属于HTML/CSS专栏文章&#xff0c;适合WEB前端开发入门学习&#xff0c;详细介绍HTML/CSS如果使用&#xff0c;如果对你有所帮助请一键三连支持&#xff0c;对博主系列文章感兴趣点击下方专栏了解详细。 博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;HTML/CS…

伪静态web.config常见规则写法与参数介绍说明

伪静态web.config常见规则写法与参数介绍说明. 示例1&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <configuration><system.webServer><rewrite><rules><rule name"规则 1" stopProcessing"tru…

微信小程序 - 调用微信 API 回调函数内拿不到 this 问题(解决方案)

微信小程序 - 调用微信 API 回调函数内拿不到 this 问题【解决方案】 tips: 本人是个小白选手&#xff0c;最近使用TP框架和微信小程序做前后端分离中&#xff08;因为前端不是很懂&#xff09;&#xff0c;经常遇到的一个问题就是在微信小程序的内置API回调函数中&#xff0c;…