归并排序概述
归并排序是建立在归并操作上一种有效的排序算法,该算法采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
排序原理
排序原理:
- 尽可能的将一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组 的元素个数是1为止。
- 将相邻的两个子组进行合并成一个有序的大组。
- 不断的重复步骤2,直到最终只有一个组为止。
排序图解
{8,4,5,7,1,3,6,2}进行从小到大排序
代码实现
实现的api:
- public static boolean greater( int a,int b) 比较a与b的大小,返回true/false
- public 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)
缺点就是,需要申请额外的空间数组,当待排序的数量较多时,会导致空间复杂度复杂