归并排序(JS版)

归并排序的时间复杂度为O(nlogn),属于稳定排序(需要额外空间)。

其是一种采用分治法的典型的算法应用。

该排序算法的主体思想:

1. “分治”:不断将当前数组从中点处分割(直至末尾被分割的数组只有1个元素),不断将复杂的大问题拆解为易于处理的小问题;

2. “合并”:当拆分后的子数组长度为1时,开始由底向上进行合并操作(将当前子数组排序后合并),直至合并至原数组,此时完成了排序;

 

示例代码1(返回新数组):

 1 /**
 2  * 归并排序
 3  * @param {number[]} arr - 待排序数组
 4  * @return {number[]} 排序后的新数组
 5  */
 6 function mergeSort(arr) {
 7   const len = arr.length;
 8   if (len < 2) return arr;
 9   // --- “分”
10   const m = Math.floor(len / 2);
11   const left = arr.slice(0, m);
12   const right = arr.slice(m);
13   // --- “合”
14   return merge(mergeSort(left), mergeSort(right));
15 }
16 
17 /**
18  * 合并数组(排序)
19  * @param {number[]} A - 子数组(左)
20  * @param {number[]} B - 子数组(右)
21  * @return {number[]} 合并且排序后的数组
22  */ 
23 function merge(A, B) {
24   const merged = [];
25   while (A.length > 0 && B.length > 0) {
26     if (A[0] <= B[0]) {
27       merged.push(A.shift());
28     } 
29     else {
30       merged.push(B.shift());
31     }
32   }
33 
34   if (A.length > 0) {
35     merged.push(...A);
36   } 
37   else if (B.length > 0) {
38     merged.push(...B);
39   }
40 
41   return merged;
42 }

 

示例代码2(修改原数组):

 1 /**
 2  * 归并排序
 3  * @param {number[]} nums - 待排序的数组
 4  * @param {number} l - 左端点索引
 5  * @param {number} r - 右端点索引
 6  */
 7 function mergeSort(nums, l, r) {
 8   // 终止条件
 9   if (l >= r) return;
10   // 分治
11   const m = ((r - l) >> 1) + l;
12   mergeSort(nums, l, m);
13   mergeSort(nums, m + 1, r);
14   // 合并
15   // 拷贝nums的[l, r]区间内的元素,对应到tmp的[0, r - l];
16   const tmp = nums.slice(l, r + 1);
17   // i 指向tmp数组中左半部的起点
18   let i = 0;
19   // j 指向tmp数组中右半部的起点
20   let j = m - l + 1;
21   // 对nums[l, r]区间的元素进行赋值重排,参照tmp的数据备份
22   for (let k = l; k <= r; k++) {
23     // 如果当前区间内的左半部已走完
24     if (i === m - l + 1) {
25       nums[k] = tmp[j++];
26     }
27     // 如果当前区间内的右半部已走完 或 左半部当前索引的元素小于等于对应右半部的
28     else if (j === r - l + 1 || tmp[i] <= tmp[j]) {
29       nums[k] = tmp[i++];
30     }
31     // 右半部当前索引的元素小于对应左半部的
32     else {
33       nums[k] = tmp[j++];
34     }
35   }
36 }

 

 

End

 

posted @ 2022-04-15 12:55  樊顺  阅读(152)  评论(0编辑  收藏  举报