归并排序,比想象中简单太多了
学习归并排序,首先,对于概念肯定要记忆,就像快排,如果没有概念,一切都是浮云,神仙也写不出代码。
快排的概念是:定义pivot,找到pivot位置并交换大小元素,然后递归。
归并的概念是:先拆分成基础元素,然后不停进行合并;合并的时候构建两个临时数组,然后临时数组合并。
public static void main(String[] args) {System.out.println("quick sort");int[] arr = new int[]{2, 4, 1, 5, 3};mergeSort(arr, 0, arr.length - 1);for (int i : arr) {System.out.println("" + i);}}private static void mergeSort(int[] arr, int left, int right) {//1.left == right 就没必要了if (left < right) {//2.找middle// / \// / \// / \// \ /// \ /// \ ///整个算法递归有点类似上面这个图//和快排的区别:快排是先partition,再进行递归;归并排序是先递归,最后合并int middle = (left + right) / 2;mergeSort(arr, left, middle);mergeSort(arr, middle + 1, right);mergeArr(arr, left, middle, right);}}/*** 这一步的目的其实是:* <p>* 将left--->middle组成的arr1 和 middle1--->right组成的arr2进行有序合并*/private static void mergeArr(int[] arr, int left, int middle, int right) {//1.首先构建 arr1 和 arr2int arr1Length = middle - left + 1;int[] arr1 = new int[arr1Length];int arr2Length = right - middle;int[] arr2 = new int[arr2Length];for (int i = 0; i < arr1Length; i++) {arr1[i] = arr[left + i];}for (int i = 0; i < arr2Length; i++) {arr2[i] = arr[middle + 1 + i];}//上面整个逻辑都是为了构建两个arr,虽然代码多,但是逻辑不复杂//涉及到一个点是边界条件,判断边界条件,我习惯用具体例子去带入。//比如 [1,2,3,4,5]的数组 left = 0, right = 4, middle = 2//所以那个+1,其实给arr1,arr2都行,只要构建的数据准确//2.合并两个有序数组int i = 0;int j = 0;int k = left;while (i < arr1Length && j < arr2Length) {if (arr1[i] < arr2[j]) {arr[k] = arr1[i];i ++;} else {arr[k] = arr2[j];j ++;}k ++;}while (i < arr1Length) {arr[k] = arr1[i];i++;k++;}while (j < arr2Length) {arr[k] = arr2[j];j++;k++;}//合并两个数组实在是太常见的一个算法了,个人认为和数组元素交换一样基础,需要达到熟读背诵的情况。//后续我会整理一些熟记的算法(flag),这些是所有算法的基础,必须要牢牢掌握的。//其中需要理解的是 k == left,倒推一下倒也明白了,总不能k==0吧,这样每次递归的时候//都在赋值相同元素了。}
排序算法大多数是分治法,先解决小部分的问题,然后将小部分进行合并,则整体有序。
