一、思路
说明:可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。分阶段可以理解为就是递归拆分子序列的过程。
二、结论
- 当左边的下标小于右边下标时,可以进行拆分,左边拆完拆右边
- 当左右两边拆分到只有单个元素时,方可进行合并。
- 合并时要知道每组的中间下标,中间下标两边的值进行比较,然后存放到temp临时数组中
- 把有剩余数据的一边的数据依次全部填充到temp
- 将temp数组的元素拷贝到array
- 注意,并不是每次都拷贝所有
- debug多跑几次,思路更清晰
三、代码
public class MergeSort {
public static void main(String[] args) {
int[] array = new int[]{ 8, 4, 5, 7, 1, 3, 6, 2 };
int[] temp = new int[array.length];
mergeSort(array,0,array.length -1,temp);
System.out.println(Arrays.toString(array));
}
public static void mergeSort(int[] array, int left, int right, int[] temp){
if (left < right){
int mid = (left + right) / 2;
// 分左边的
mergeSort(array, left, mid, temp);
// 分右边的
mergeSort(array, mid+1, right, temp);
//
merge(array,left,mid, right ,temp);
}
}
//合并的方法
/**
*
* @param array 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void merge(int[] array, int left,int mid, int right, int[] temp){
// int mid = (left + right) / 2;
int i = left; // 初始化i, 左边有序序列的初始索引
int j = mid + 1; //初始化j, 右边有序序列的初始索引
int t = left;// 指向temp数组的当前索引
//先把左右两边(有序)的数据按照规则填充到temp数组
//直到左右两边的有序序列,有一边处理完毕为止
while (i < mid + 1 && j <= right){
//如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
//即将左边的当前元素,填充到 temp数组
//然后 t++, i++
if (array[i] < array[j]){
temp[t] = array[i];
i += 1;
t += 1;
}else {
temp[t] = array[j];
j += 1;
t += 1;
}
}
//(二)
//把有剩余数据的一边的数据依次全部填充到temp
while (i < mid +1){//左边的有序序列还有剩余的元素,就全部填充到temp
temp[t] = array[i];
i += 1;
t += 1;
}
while (j <= right){
temp[t] = array[j];
j += 1;
t += 1;
}
//(三)
//将temp数组的元素拷贝到arr
//注意,并不是每次都拷贝所有
int tempLift = left;
//第一次合并 tempLeft = 0 , right = 1 // tempLeft = 2 right = 3 // tL=0 ri=3
//最后一次 tempLeft = 0 right = 7
while (tempLift <= right){
array[tempLift] = temp[tempLift];
tempLift += 1;
}
}
}

京公网安备 11010502036488号