这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
归并排序
之前我们学到的冒泡排序、选择排序、插入排序因为性能不好的原因,而在实际的开发过程中几乎很少用到。而我们现在要准备学的归并排序性能不错,在实际开发中用的较多。
归并排序:
是一种分治算法。其思想是
:将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。
归并排序 利用了 递归
。
实现
// 声明mergeSort方法,传入待排序数组
function mergeSort(arr) {
// mergeSortRec是一个递归函数
let arrTemp = mergeSortRec(arr)
return arrTemp
}
// 实现 mergeSortRec方法
function mergeSortRec(arr) {
let len = arr.length
// 根据归并的核心思想,如果待排序数组长度为1,说明已经排好序了,直接返回
if (len === 1) {
return arr
}
// 找到数组的中间位置,将数组一分为二,分为左右两个数组,然后对切分之后的数组再分别进行二等分,一直递归到数组长度为1时结束
let mid = Math.floor(len / 2);
let left = arr.slice(0, mid)
let right = arr.slice(mid, len)
// merge方法用来将小数组排序并最终合并成大数组
return merge(mergeSortRec(left), mergeSortRec(right))
}
// 实现merge函数,接收两个数组作为参数,并最终将其归并为一个大数组返回。
// 在归并的过程中进行排序
function merge(left, right) {
// 定义变量 接收最终的数组
let result = []
// 左侧数组的循环起始点
let il = 0;
// 右侧数组的循环起始点
let ir = 0;
// 如果left数组中当前项,比right数组中的当前项小,那么将left数组中取出当前项,push到result数组中,并将当前迭代的i加1,否则将right数组中的当前项push到result中,同样的将迭代的i加1
while (il < left.length && ir < right.length) {
if (left[il] < right[ir]) {
result.push(left[il++])
} else {
result.push(right[ir++])
}
}
// 左右两个数组都迭代完毕之后,分别将两个数组中剩余的元素,push到result数组中
while (il < left.length) {
result.push(left[il++])
}
while (ir < right.length) {
result.push(right[ir++])
}
// 最后将结果数组返回
return result
}
首先是将原始数组分割,直至只有一个元素的子数组,然后才开始归并。在归并的过程中完成排序。