歸併排序的思想:將數組分爲左右兩部分,分別將左半部分數組排爲有序數組,將右半部分數組排爲有序數組,然後再將兩部分數組排序合併;在對左半部分數組和右半部分排序時,又引用了上面的思想,所以就引入了遞歸思想;
import java.util.Arrays;
public class GuiBing {
public static void GuiBingSort(int[] array) {
guiBingInner(array, 0, array.length);//左閉右開,數組排序的範圍
}
private static void guiBingInner(int[] array, int left, int right) {
if (left + 1 == right) {//如果只剩一個數就排完序了,就退出了,這是遞歸的出口
return;
}
/*找出中間數的下標*/
int mid = (left + right) / 2;
/*分別對左半部的數組進行歸併排序,對右半部分的數組進行歸併排序,採用遞歸的方法*/
guiBingInner(array, left, mid);
guiBingInner(array, mid, right);
/*然後再將排好序的左半部分[left,mid)和右半部分數組[mid,right)進行合併*/
merge(array, left, mid, right);
}
private static void merge(int[] array, int left, int mid, int right) {
/*需要一個額外的數組*/
int[] extra = new int[right - left];
/*將[left,mid)數組和[mid,right)數組合並*/
int p = left; //[left,mid)數組的起始位置
int q = mid; //[mid,right)數組的起始位置
int i = 0;
while (p < mid && q < right) {
if (array[p] <= array[q]) {
extra[i] = array[p];
i++;
p++;
} else if (array[q] < array[p]) {
extra[i] = array[q];
i++;
q++;
}
}
while (p < mid) {
extra[i] = array[p];
i++;
p++;
}
while (q < right) {
extra[i] = array[q];
i++;
q++;
}
/*最後再將extra數組中的值返回放到array原數組中*/
for (int k = 0; k < extra.length; k++) {
array[k + left] = extra[k];
}
}
public static void main(String[] args) {
int[] array = new int[]{1, 7, 4, 9, 2, 4, 6, 8, 5, 17, 23, 12};
GuiBingSort(array);
System.out.println(Arrays.toString(array));
}
}
調用過程如下:
用gBI代替guiBingInner函數名:
從上往下進行gBI,在每一層gBI中又調用gBI函數,然後再將值從下往上返回,然後再從下往上進行排序合併:
gBI(0,1)之後得到1,
gBI(1,2)之後得到7,
將1和7進行排序合併:{1,7},自此gBI(0,2)也就完成了;
gBI(2,3)之後得到4,
再將gBI(0,2)與gBI(2,3)的得到的數進行排序,得到{1,4,7},自此gBI(0,3)也就完成了;
同理,gBI(3,6)中是通過:
gBI(3,4)之後得到9,
gBI(4,5)之後得到2,
將9和2進行排序合併:{2,9},自此gBI(3,5)也就完成了;
gBI(5,6)之後得到4,
再將gBI(3,5)與gBI(5,6)的得到的數進行排序,得到{2,4,9},自此gBI(3,6)也就完成了
再將gBI(0,3)得到的數組{1,4,7}與gBI(3,6)得到的數組{2,4,9}進行排序合併,得到{1,2,4,4,7,9},自此gBI(0,6)完成;
gBI(6,12)的調用過程也是如此;
再將gBI(0,6)得到的數組值與gBI(6,12)得到的數組值進行排序合併得到:[1, 2, 4, 4, 5, 6, 7, 8, 9, 12, 17, 23]