时间复杂度: O(nlogn)
空间复杂度: O(n)
稳定性:稳定
我们由上图逐步分析归并算法的思想,其实可以看出将数据先分解后合并,这是用到了分治思想
分解:
分解其实就是先找到数组的中点,分成两段,按照这种方法知道不可分为止
合并:
合并是一个边排序边合并的过程,需要一个中间数组来完成
通过分析我们可以看出无论是分解还是合并都是重复一些过程,所以使用递归无疑是一种很方便的方法
对于归并排序一定要搞清楚下标我们首先来进行分解
Main:
public static void main(String[] args) { int[] Array={10,6,7,1,3,9,4,2}; System.out.println(Arrays.toString(Array)); MergeSort(Array,0,Array.length-1); System.out.println("MergeSort After:"); System.out.println(Arrays.toString(Array)); }MergeSort:
public static void MergeSort(int[] Array,int left,int right){ if(left>=right){ return; } int mid=(left+right)>>>1; MergeSort(Array,left,mid); MergeSort(Array,mid+1,right); Merge(Array,left,mid,right); } 首先判断传入的区间下标,如果传入错误直接return即可 1.计算中间下标 2.先递归左侧,注意参数是left和mid 3.再递归右侧,参数是mid+1和right 这样我们就可以得到左侧和右侧递归的结果 递归完成后就可以准备排序合并了合并:
public static void Merge(int[] Array,int left,int mid,int right){ int s1 = left; int s2 = mid+1; int[] temp=new int[right-left+1]; //临时数组 int i=0; //temp 数组的下标 while(s1 <= mid && s2 <= right){ if(Array[s1] <= Array[s2]){//稳定排序的关键 temp[i++] = Array[s1++]; }else{ temp[i++] = Array[s2++]; } } while(s1 <= mid){ temp[i++] = Array[s1++]; } while(s2 <= right){ temp[i++] = Array[s2++]; } for (int j = 0; j < temp.length; j++) { Array[j+left]=temp[j]; } } 以这里为例 左侧10的下标是left 也是mid 右侧6的下标是mid+1 也是right 我们设置一个临时数组用来存放临时排序后的值,注意排序完成后我们得到一个temp={6,10}的数组 同理7和1排序后也生成一个temp={1,7} 我们要将两个temp合并到array数组中首先6和10不用说了直接移入 但是如果我们使用 for (int j = 0; j < temp.length; j++) { Array[j]=temp[j]; } 这样的化1和7就会从头插入,就会覆盖掉6和10所以循环里j要加上left 对于6和10 left为0 对于1和7 left为上一步的mid+1 也就是2 这样插入就没有问题了
public static void main(String[] args) { int[] Array={10,6,7,1,3,9,4,2}; System.out.println(Arrays.toString(Array)); MergeSort(Array,0,Array.length-1); System.out.println("MergeSort After:"); System.out.println(Arrays.toString(Array)); } public static void MergeSort(int[] Array,int left,int right){ if(left>=right){ return; } int mid=(left+right)>>>1; MergeSort(Array,left,mid); MergeSort(Array,mid+1,right); Merge(Array,left,mid,right); } public static void Merge(int[] Array,int left,int mid,int right){ int s1 = left; int s2 = mid+1; int[] temp=new int[right-left+1]; //临时数组 int i=0; //temp 数组的下标 while(s1 <= mid && s2 <= right){ if(Array[s1] <= Array[s2]){//稳定排序的关键 temp[i++] = Array[s1++]; }else{ temp[i++] = Array[s2++]; } } while(s1 <= mid){ temp[i++] = Array[s1++]; } while(s2 <= right){ temp[i++] = Array[s2++]; } for (int j = 0; j < temp.length; j++) { Array[j+left]=temp[j]; } }