归并排序
归并排序是建立在归并操作上的一种有效的算法,采用到了分治法的思想,将已经有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序,若将两个有序表和并成一个有序表,称为二路归并。
基本原理
1、将一组数据尽可能的拆分成两个元素相等的子组,并对每一个子组继续进行拆分,直到拆分后的每个子组的元素个数为1为止。
2、将相邻的两个子组进行合并成一个有序的大组。
3、不断的重复步骤2,直到最终只有一个组为止。
图解
上附图中的具体操作如下,后面和并时的操作与之一样
具体代码
//要点:递归,重载
public class MergeSort {
//辅助数组
//Comparable[] 数组assist是实现Comparable接口的类的数组。【这个数组中的元素都是comparable接口类型,可以调用compareTo方法】
private static Comparable[] assist;
//判断两个元素之间的大小
private static boolean less(Comparable v, Comparable w){
return v.compareTo(w)<0;
}
//对数组a的排序
public static void sort(Comparable[] a){
//初始话辅助数组
assist = new Comparable[a.length];
//定义lo变量,hi变量,分配记录数组中最小的索引和最大的索引
int lo = 0;
int hi = a.length-1;
//调用sort重载方法完成数组a中,从索引lo到索引hi的元素的排序
sort(a,lo,hi);
}
//对数组a从lo到hi的元素进行排序
private static void sort(Comparable[] a, int lo, int hi){
//安全性检验
if(hi<=lo){
return;
}
//将lo到hi之间的数组分成两个组
int mid = lo+(hi-lo)/2;
//分别对每一组进行排序
sort(a,lo,mid);
sort(a,mid+1,hi);
//归并两个数组
merge(a,lo,mid,hi);
}
//lo到mid为一组,mid+1到hi为一组,对数组中的这两组进行归并
private static void merge(Comparable[] a, int lo, int mid, int hi){
//定义三个指针
int i = lo;
int p1 = lo;
int p2 = mid+1;
//遍历指针:移动p1,p2指针
while(p1<=mid && p2<=hi){
if(less(a[p1],a[p2])){
assist[i++] = a[p1++];
}else{
assist[i++] = a[p2++];
}
}
//如果p1指针没有走完,则移动p1指针,将对应元素移动到辅助数组对应索引处
while(p1<=mid ){
assist[i++] = a[p1++];
}
//如果p2指针没有走完,则移动p1指针,将对应元素移动到辅助数组对应索引处
while(p2<=hi){
assist[i++] = a[p2++];
}
//将辅助数组复制到原数组中
for(int index = lo; index<=hi; index++){
a[index] = assist[index];
}
}
}