核心思想:递归,无线分组
对于一组需要排序的数字数组,首先寻找middle点,将这串数字分成两组,左边数组称为A,右边数组称为B,对于A,继续寻找middle点,将A分为两组,对于这两组数据继续使用同样的方式分组,如此循环,直至每个数组的元素仅有一个,对于数组B也是同样的方式。。。此时,需要被排序的数组被分为拥有元素均为1的数组,如下图绿色元素部分。
由于数组都是被一分为二的,如下图所示,所以自下而上将数组中的元素合并排序
合并方式:对于数组A[a0,a1,a2,a3,a4] 和 B[b0,b1,b2,b3,b4]
首先创建一个数组C,比较A[a0]和B[b0],如果A[a0]<B[b0],那么将A[a0]赋值给C[c0],然后a0和c0下标均向后移动一位,变为a1,c1
如果A[a0]>B[b0],那么将B[b0]赋值给C[c0],然后b0和c0下标均向后移动一位,变为b1,c1
利用这种方式,从两个数组最开始的元素进行比较,哪个元素小,则将该元素值赋值给新数组C下标为0的第一个元素,然后将两个元素所在的下标分别+1,然后继续比较,直至其中一个数组的元素被完全分配到数组C中,此时,将另一个数组中的剩余元素依次添加到数组C中,此时数组C便是两个数组合并并排序的最终结果
图解思想过程
完整代码
package sort;
public class MergeSort {
public static void mergeSort(int[] array, int left, int right) {
//如果数组最左边的下标小于数组最右边的下标,说明该数组不止一个元素,则继续进行分组
if(left < right) {
int middle = (right + left) / 2;
mergeSort(array, left, middle);
mergeSort(array, middle + 1, right);
//将array分为的两个数组进行排序合并
merge(array, left, right, middle);
}
}
public static void merge(int[] array, int left, int right, int middle) {
int[] tmpArray = new int[array.length]; //创建一个临时数组
int leftTmp = left;
int rightTmp = middle + 1; //将右边数组的起始下标记为rightTmp
int tmpArrayIndex = left; //将临时数组的其实下标记为tmpArrayIndex
//当两个数组元素都没有被比较完时
while(left <= middle && rightTmp <= right) {
//左边数组的元素小,则将该元素添加到新数组中,并将两个数组的下标都+1
if(array[left] <= array[rightTmp]) {
tmpArray[tmpArrayIndex++] = array[left++];
} else { //否则,将右边元素添加到新数组中,并将两个数组的下标都+1
tmpArray[tmpArrayIndex++] = array[rightTmp++];
}
}
//程序进行到这一步,说明已经有一个数组元素被完全分配
//如果左边数组元素有剩余,则将左边数组的剩余元素依次添加到新数组中
while(left <= middle) {
tmpArray[tmpArrayIndex++] = array[left++];
}
//如果右边数组元素有剩余,则将右边数组的剩余元素依次添加到新数组中
while(rightTmp <= right) {
tmpArray[tmpArrayIndex++] = array[rightTmp++];
}
//最后,将新数组(临时数组)中的所有元素值依次赋值给需要排序的数组(形参中传来的数组)
while(leftTmp <= right) {
array[leftTmp] = tmpArray[leftTmp++];
}
}
}
测试代码
package sort;
import static sort.MergeSort.mergeSort;
public class Test {
public static void main(String[] args) {
int[] array = new int[]{2, 9, 1, -5, 32, 31, 6, -5, 22, 0};
mergeSort(array, 0, array.length - 1);
for(int i : array) {
System.out.println(i);
}
}
}