归并排序是运用了分治的思想,将整个数组分成若干个部分,直到分成单个元素,依次排序,这里只演示分治的最后一步,也是最便于理解的一步,见下:此时在 left —— mid 这一边是有序的,mid + 1 —— right 这一部分也是有序的,开始进行 merge
定义两个指针,一个指针 i 指向 left,另一个指针 j 指向 mid + 1 的位置,目的在于遍历两个数组,此时 a[i] < a[j],我们将 i 指针所指向的位置拿出来,是整个数组最小的元素,然后让 i 指针向后移,同理
同时往后移,当 i 大于 mid 或者 j 大于 right 时,只移动其中一边的元素(有点像链表的合并)
最后的结果:
import java.util.*;
public class Main {
public static void main(String[] args) {
int[] a = new int[]{1, -1, 55, 100, 85, 999, 33, 98, 12, 4};
System.out.println(Arrays.toString(a));
mergeSort(a, 0, a.length - 1);//分治思想,每次将子数组分为两部分
System.out.println(Arrays.toString(a));
}
private static void mergeSort(int[] a, int left, int right) {
if(left >= right) return;
int mid = left + (right - left) / 2;
mergeSort(a, left, mid);
mergeSort(a, mid + 1, right);
merge(a, left, mid, right);//分完既合,分分合合
}
private static void merge(int[] a, int left, int mid, int right) {
int[] b = new int[right - left + 1];//需要辅助数组
for(int i = left; i <= right; i++) {
b[i - left] = a[i];
}
//这块别看代码很多很乱,其实一看一分析就懂,超级好理解
int i = left, j = mid + 1;
for(int k = left; k <= right; k++) {
if(i > mid) {
a[k] = b[j - left];
j++;
} else if (j > right) {
a[k] = b[i - left];
i++;
} else if (i < j && b[i - left] < b[j - left]) {
a[k] = b[i - left];
i++;
} else {
a[k] = b[j - left];
j++;
}
}
}
}