归并排序的原理、图解、代码实现、时间复杂度分析

    技术2022-07-11  81

    归并排序

    归并排序概述排序原理排序图解代码实现具体实现合并的图解代码实现 时间复杂度分析

    归并排序概述

    归并排序是建立在归并操作上一种有效的排序算法,该算法采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

    排序原理

    排序原理:

    尽可能的将一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组 的元素个数是1为止。将相邻的两个子组进行合并成一个有序的大组。不断的重复步骤2,直到最终只有一个组为止。

    排序图解

    {8,4,5,7,1,3,6,2}进行从小到大排序

    代码实现

    实现的api:

    public static boolean greater( int a,int b) 比较a与b的大小,返回true/falsepublic static void exch(int[] a,int i,int j) 交换索引i处和索引j处的值的位置public static void sort(int[] a) 对数组a进行排序public static void sort(int[] a,int lo,int hi) 对数组指定索引lo到指定索引hi处的值进行排序public static void merge(int[] a,int lo,int mid,int hi) 将索引lo到索引mid的数组和索引mid+1到索引hi的数组合并成一个数组

    具体实现合并的图解

    代码实现

    import java. util .Arrays; public class SortMerge { //定义辅助数组 private static int[] help; public static void main(String[] args) { int[] array=new int[]{8,4,5,7,1,3,6,2}; sort(array); System. out. println(Arrays . toString(array)); } /** * 比较两个数之间的大小 * @param a * @param b * @return */ public static boolean greater( int a,int b){ return a>b; } /** * 交换两个数的位置 * @param a * @param i * @param j */ public static void exch(int[] a,int i,int j){ int temp=a[i]; a[i]=a[j]; a[j]=temp; } /** * 对元素进行排序 * @param a */ public static void sort(int[] a){ //初始化辅助数组 help=new int[a. length]; int lo=0; int hi=a.length-1; //从lo索引处到hi所引处进行排序 sort(a,lo,hi); } /** * 对数组元素从索引到索引的排序 * @param a * @param lo * @param hi */ public static void sort(int[] a,int lo,int hi){ if(hi<=lo){ return; } //对lo-hi之间数据进行分组 int mid=(lo+hi)/2; //分别每一组数据进行排序 sort(a,lo,mid); sort(a,mid+1,hi); //排完序后对两个数组进行归并 merge(a,lo,mid,hi); } /** * 再把两个组中数组进行归并 * 从索引1o- mid是一个数组, mid+1- hi又是一-个数组 ,将两个数组合并 * @param a * @param lo * @param mid * @param hi */ public static void merge(int[] a,int lo,int mid,int hi){ int i=lo;//辅助数组的指针 //左子数组的指针 int p1=lo; //右子数组的指针 int p2=mid+1; //归并的时候,当左子数组和右子数组都还没有遍历完的时候 while(p1<=mid && p2<=hi){ //比较两个索引处的值的大小,如果左子数组的当前索引处的值大于右子数组当前索引处的值,则将右子数组索引处的值放到辅助数组中,并且右子数组的指针右移,否则相反 if(greater(a[p1],a[p2])){ help[i++]=a[p2++]; }else{ help[i++]=a[p1++]; } } //当上面while循环结束后,左子数组还没有遍历完,则直接按顺序放入到辅助数组中 while(p1<=mid){ help[i++]=a[p1++]; } //当上面while循环结束后,右子数组还没有遍历完,则直接按顺序放入到辅助数组中 while(p2<=hi){ help[i++]=a[p2++]; } //将辅助数组的值放到数组张 for(int index=lo;index<=hi ;index++){ a[index]=help[index]; } } }

    时间复杂度分析

    时间复杂度为O(nlogn) 缺点就是,需要申请额外的空间数组,当待排序的数量较多时,会导致空间复杂度复杂

    Processed: 0.024, SQL: 9