歸並排序可以采用遞歸方法(見:歸並排序),但遞歸方法會消耗深度位O(longn)的棧空間,使用歸並排序時,應該盡量使用非遞歸方法。本文實現了java版的非遞歸歸並排序。
更多:數據結構與算法合集
思路分析
遞歸排序的核心是merge(int[] arr, int start, int mid, int end)函數,講[start~mid-1]和[mid~end]部分的數據合並,遞歸代碼是使用遞歸得到mid,一步步分解數組。
非遞歸時,我們直接定義要合並的小數組長度從1開始,在較小的長度數組都合並完成后,令長度*2,繼續進行合並,直到合並完成。
完整Java代碼
(含測試代碼)
public class MergeSort2 {
public void mergeSort(int[] arr) {
if(arr==null || arr.length<=0)
return;
int width = 1;
while(width<arr.length) {
mergePass(arr,width);
width*=2;
}
}
private void mergePass(int[] arr,int width) {
int start=0;
while(start+2*width-1<arr.length) {
int mid=start+width-1;
int end=start+2*width-1;
merge(arr,start,mid,end);
start=start+2*width;
}
//剩余無法構成完整的兩組也要進行處理
if(start+width-1<arr.length)
merge(arr, start, start+width-1, arr.length-1);
}
private void merge(int[] arr, int start, int mid, int end) {
int i=start;
int j=mid+1;
int[] temp = new int[end-start+1];
int index=0;
while(i<=mid && j<=end) {
if(arr[i]<=arr[j])
temp[index++]=arr[i++];
else
temp[index++]=arr[j++];
}
while(i<=mid)
temp[index++]=arr[i++];
while(j<=end)
temp[index++]=arr[j++];
for(int k=start;k<=end;k++)
arr[k]=temp[k-start];
}
//==========測試代碼=================
public void test1() {
int[] a = null;
mergeSort(a);
System.out.println(Arrays.toString(a));
}
public void test2() {
int[] a = {};
mergeSort(a);
System.out.println(Arrays.toString(a));
}
public void test3() {
int[] a = { 1 };
mergeSort(a);
System.out.println(Arrays.toString(a));
}
public void test4() {
int[] a = { 3, 3, 3, 3, 3 };
mergeSort(a);
System.out.println(Arrays.toString(a));
}
public void test5() {
int[] a = { -3, 6, 3, 1, 3, 7, 5, 6, 2 };
mergeSort(a);
System.out.println(Arrays.toString(a));
}
public static void main(String[] args) {
MergeSort2 demo =new MergeSort2();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
}
}
MergeSort2
更多:數據結構與算法合集
