思想:
分治思想,将数组先分成前后两部分吗,分别通过递归调用将他们单独排序,最后将有序的子数组归并成最终排序结果。
//归并排序(递归思想)
public class Merge {
//定义辅助数组arr
private static Comparable[] arr;
/*
对数组元素进行排序
*/
public static void sort(Comparable[] a){
//初始化辅助数组
arr = new Comparable[a.length];
int min = 0;
int max = a.length-1;
sort(a,min,max);
}
/*
对数组a中从索引min到索引max之间的元进行排序
*/
private static void sort(Comparable[] a,int min,int max){
//排除不符合情况
if(min >= max){
return;
}
int mid = min + (max-min)/2;//记录中间位置索引
//将前后两部分排序
sort(a,min,mid);
sort(a,mid+1,max);
//将前后两组归并
mergr(a,min,mid,max);
}
/*
从索引min -> mid为一个子组,从索引mid+1 -> max为另一个子组,把数组a中这两个子组数据合并成一个有序的大组
*/
private static void mergr(Comparable[] a,int min,int mid,int max){
//定义三个指针
int i = min;//辅助数组
int p1 = min;//前一个数组第一个元素
int p2 = mid+1;//后一个数组第一个元素
//遍历p1和p2指针所在处元素值大小,找到小的那个放到辅助数组arr对应位置中,直到其中一组遍历完
while (p1 <= mid && p2 <=max){
if(less(a[p1],a[p2])){
arr[i++] = a[p1++];
}else
arr[i++] = a[p2++];
}
//将p1或者p2剩余的元素全部储存到辅助数组arr中
while (p1 <= mid){
arr[i++] = a[p1++];
}
while (p2 <= max){
arr[i++] = a[p2++];
}
//将辅助数组arr中元素复制到a数组中
for(int j = min;j <= max; j++){
a[j] = arr[j];
}
}
/*
比较v元素是否小于w元素
*/
private static boolean less(Comparable v, Comparable w){//实现了compare接口的类均可使用
return v.compareTo(w) < 0;
}
/*
数组元素i和j交换位置
*/
private static void exch(Comparable[] a,int i,int j){
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
测试代码:
public class MergeTest {
public static void main(String[] args) {
Integer[] arr = {4,6,7,3,1,8,9,5,2};
Merge.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
注意:
1、时间复杂度为O(n*logn);
2、需要辅助数组!空间换时间