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);