归并排序的思想:将数组分为左右两部分,分别将左半部分数组排为有序数组,将右半部分数组排为有序数组,然后再将两部分数组排序合并;在对左半部分数组和右半部分排序时,又引用了上面的思想,所以就引入了递归思想;
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]