介绍
归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
递归算法
使用递归的代码如下。优点是描述算法过程思路清晰,缺点是使用递归,mergeSort()函数频繁地自我调用。长度为 n 的数组最终会调用 mergeSort()函数 2n-1 次,这意味着一个长度超过 1500 的数组会在 Firefox 上发生栈溢出错误。可以考虑使用迭代来实现同样的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function merge(left, right) { var result = []; while (left.length > 0 && right.length > 0) { if (left[0] < right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } return result.concat(left).concat(right); } function mergeSort(items) { if (items.length == 1) { return items; } var middle = Math.floor(items.length / 2), left = items.slice(0, middle), right = items.slice(middle); return merge(mergeSort(left), mergeSort(right)); }
|
非递归算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| function mergePass( arr = [], temp = new Array(arr.length), N = arr.length, length = 1 ) { let t; for (t = 0; Math.pow(2, t) < N; t++, length *= 2) { const even = t % 2 === 0; for (let left = 0; left < N; left += 2 * length) { const middle = left + length < N ? left + length : left; const right = left + 2 * length < N ? left + 2 * length : N; merge(even ? arr : temp, even ? temp : arr, left, middle, right); } } if (t % 2 === 0) { return arr; } return temp; } function merge(arr, temp, left, middle, right) { const leftEnd = middle - 1; while (left <= leftEnd && middle < right) { if (arr[left] > arr[middle]) { temp[left + middle - leftEnd - 1] = arr[middle++]; } else { temp[left + middle - leftEnd - 1] = arr[left++]; } } while (left > leftEnd && middle < right) { temp[left + middle - leftEnd - 1] = arr[middle++]; } while (left <= leftEnd && middle >= right) { temp[left + middle - leftEnd - 1] = arr[left++]; } }
|
动图展示
