代码如下:
//数值归并排序(非递归)
function mergesort(arr){
const temparr = [], arrlen = arr.length //临时数组、总长度
let le = 0 //放入新数组的数据的递增序号
let i, j //要比较数据的指针
let sep = 2 //比较时抽取组的元素个数(每次以2倍递增)
let flag = false //放入最新排序好的元素的数组种类(false放入临时数组,true放入原数组)
while(2*arrlen>sep){
const section = Math.ceil(arrlen/sep) //每个sep对应的分组数
for(let k = 0;k<section;k++){
i = sep*k
j = sep*k + sep/2
if(!flag){
if(j>=arrlen){ //复制末端边界处的元素(sep*kmax≤索引≤sep*kmax+sep/2内的元素已有序)
while(i<arrlen){
temparr[le++] = arr[i++]
}
break
}
const m = sep*k+sep/2, n = sep*(k+1) //每组的最大标记点
while(i<m || j<n){
if(i===m){ //复制每组剩余的有序部分(i先到达每组最大位置)
if(j!==arrlen){
temparr[le++] = arr[j++]
continue
}
break
}
if(j===n || j===arrlen){ //复制每组剩余的有序部分(j先到达每组最大位置)
temparr[le++] = arr[i++]
continue
}
temparr[le++] = arr[i]<arr[j]?arr[i++]:arr[j++] //从小到大排序
}
}
else{
if(j>=arrlen){
while(i<arrlen){
arr[le++] = temparr[i++]
}
break
}
const m = sep*k+sep/2, n = sep*(k+1)
while(i<m || j<n){
if(i===m){
if(j!==arrlen){
arr[le++] = temparr[j++]
continue
}
break
}
if(j===n || j===arrlen){
arr[le++] = temparr[i++]
continue
}
arr[le++] = temparr[i]<temparr[j]?temparr[i++]:temparr[j++]
}
}
}
flag = !flag
le = 0
sep *= 2
}
if(flag){ //对最后放入临时数组的元素需复制到原数组
for(let index=0;index<arrlen;index++){
arr[index] = temparr[index]
}
}
return arr
}
//这个是测试
console.log(mergesort([19,12,5,18,11,3,15,10,1,17,9,2,13,4,7,14,16,6,8]))