理解归并排序
归并排序是一种基于分治思想的排序算法,它将一个待排序的序列分为两个子序列,分别对子序列进行排序,然后将排好序的子序列合并成一个有序的序列。这个过程可以递归地进行,直到序列被划分为只有一个元素时停止递归。
在归并排序的过程中,将序列分为两个子序列的操作称为分治,合并两个有序子序列为一个有序序列的操作称为归并。分治和归并是归并排序的核心操作。
具体而言,归并排序的过程如下:
- 将序列递归地分为左右两个子序列,直到每个子序列只有一个元素。
- 对左右两个子序列进行归并排序,得到两个有序子序列。
- 合并两个有序子序列,得到一个有序序列。
归并排序的时间复杂度为 O(nlogn),相较于其他排序算法具有较好的稳定性和效率。
归并排序实现代码
/**
* 归并排序
* @param {要排序的数组} arr
*/
function mergeSort(arr) {
if (arr.length > 1) {
const middle = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, middle));
const right = mergeSort(arr.slice(middle, arr.length));
arr = merge(left, right);
}
return arr;
}
// 合并左分支数组和右分支数组,左分支和右分支在自己数组里面已经是有序的。所以就方便很多。
function merge(left, right) {
// 剪枝优化
if (left[left.length - 1] <= right[0]) {
return left.concat(right);
}
if (right[right.length - 1] <= left[0]) {
return right.concat(left);
}
let result = [];
let leftIndex = 0;
let rightIndex = 0;
while (leftIndex < left.length && rightIndex < right.length) {
if (left[leftIndex] <= right[rightIndex]) {
result.push(left[leftIndex]);
leftIndex++;
} else {
result.push(right[rightIndex]);
rightIndex++;
}
}
// 将剩余数据拷贝至result
if (leftIndex < left.length) {
result = result.concat(left.slice(leftIndex));
} else {
result = result.concat(right.slice(rightIndex));
}
return result;
}
实现代码详细解说
这段代码实现了归并排序,具体过程就是将待排序的数组一分为二,分别对左右两部分进行排序,然后再将排好序的两部分合并起来,这样就能得到一个完整有序的数组。
在代码中,mergeSort
函数是递归调用自己实现的排序函数。如果数组的长度大于1,就将其一分为二,分别对左右两部分进行递归排序,并最终通过merge
函数将排好序的两部分合并为一个完整的有序数组。如果数组长度小于等于1,就直接返回该数组。
merge
函数的作用就是将两个有序数组合并为一个有序数组。代码首先进行了剪枝优化,判断左右两个数组是否已经有序,如果是的话就直接将它们合并起来返回。如果不是,就使用两个指针leftIndex
和rightIndex
分别遍历左右两个数组,比较它们的元素大小,将较小的元素依次放入result
数组中。当其中一个数组遍历完了之后,就将另一个数组中剩余的元素依次拷贝至result
数组的末尾。
最后,在代码末尾,我们调用了mergeSort
函数并传入一个待排序的数组,最终得到的输出结果就是该数组排序后的结果。