注意:两种方法的实现都不改变原数组,而是生成一个新的数组。
迭代法
Array.prototype.mergeSort = function(fun/*, thisArg*/) {
'use strict';
if (this === void 0 || this === null) {
throw new TypeError();
}
if (fun && typeof fun !== 'function') {
throw new TypeError();
}
var t = Object(this);
var items = t.slice(0);
var len = t.length >>> 0;
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
function merge(left, right){
var result=[], flag = false;
while(left.length>0 && right.length>0){
/* if fun return true, left is smaller than right. */
flag = !fun ? left[0]<right[0] : fun.call(thisArg, left[0], right[0]);
if(flag){
/* shift(): delete and return the first element from array. */
result.push(left.shift());
} else{
result.push(right.shift());
}
}
/* Left is smaller than right. */
return result.concat(left).concat(right);
}
/* Iteration count = log2(len) */
var count = Math.LOG2E * Math.log(len), k = 1, j = 1, left, right, result;
while (count > 0){
result = [];
j = k * 2; // k is one group length, j is two groups' length
for (var i = 0; i < len ; i = i + j) {
left = items.slice(i, i + k);
right = items.slice(i + k, i + j );
/* console.log(left);
console.log(right);
console.log(result = result.concat(merge(left, right))); */
result = result.concat(merge(left, right));
}
items = result;
k *= 2; // group length
count--;
}
return items;
}
递归法
Array.prototype.mergeSort = function(fun/*, thisArg*/) {
'use strict';
if (this === void 0 || this === null) {
throw new TypeError();
}
if (fun && typeof fun !== 'function') {
throw new TypeError();
}
var t = Object(this);
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
function merge(left, right){
var result=[], flag = false;
while(left.length>0 && right.length>0){
/* if fun return true, left is smaller than right. */
flag = !fun ? left[0]<right[0] : fun.call(thisArg, left[0], right[0]);
if(flag){
/* shift(): delete and return the first element from array. */
result.push(left.shift());
} else{
result.push(right.shift());
}
}
/* Left is smaller than right. */
return result.concat(left).concat(right);
}
function mergeSort(items){
/* recursive method
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));
}
return mergeSort(t);
}