分析归并排序可知:最底层的合并元素之间的间隔为1,越向上,间隔则变为原来的两倍,基于此我们有如下的非递归实现方案:
package com.dlut.sort;
import org.junit.Test;
public class NoRecurMergeSort {
private int[] arr = {9,0,1,3,2,5,4,112,7,60,8,100,12,11,13,14,17,16,15,34,111};
@Test
public void printMergeSort()
{
int[] tempArr = new int[arr.length];
mergeSort(arr, tempArr, 0, arr.length-1);
for (int j = 0; j < tempArr.length; j++) {
System.out.println(tempArr[j]);
}
}
/**
* 合并数组的长度从1开始递增
* @param arr
* @param tempArr
* @param low
* @param high
*/
public void mergeSort(int[] arr,int[] tempArr,int low,int high)
{
for(int i=1;2*i< arr.length;i *= 2) //合并数组的长度
{
for (int j = 0; j < tempArr.length; j+=i) { //合并
if (j+i <= arr.length) {
mergeArr(arr, tempArr, (2*j+i-1)/2, j, j+i-1);
}
mergeArr(arr, tempArr, (j+arr.length-1)/2, j, arr.length-1);
}
}
mergeArr(arr, tempArr, (low + high)/2, low, high);
}
/**
* 合并函数:合并两个相邻的有序的数组
* @param arr
* @param tempArr
* @param center
* @param low
* @param high
*/
public void mergeArr(int[] arr,int[] tempArr,int center,int low,int high)
{
int leftlow = low,temppos = low;
int rightlow = center + 1;
while (leftlow <=center && rightlow <= high) {
if (arr[leftlow]<=arr[rightlow]) {
tempArr[temppos++] = arr[leftlow++];
}
else {
tempArr[temppos++] = arr[rightlow++];
}
}
while (leftlow <=center)
tempArr[temppos++] = arr[leftlow++];
while (rightlow <= high)
tempArr[temppos++] = arr[rightlow++];
/*
* 这一步是必须的,因为你是在arr上进行归并排序。一定要将本次的结果放到arr上。
* 试想如果没有放入arr中,则会出现,某一位置的元素经过多次的交换后又回到该位置
*/
for (int i = low; i <= high; i++) {
arr[i] = tempArr[i];
}
}
}