归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,
该算法采用经典的分治(divide and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案”修补"在一起,即分而治之)。
归并排序基本思想
合并相邻有序子序列:
治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将
[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class MergeSort {
public static void sort(int array[],int left,int right,int temp[]){
if(left<right){
//中间索引
int mid=(left+right)/2;
//向左递归进行分解
sort(array,left,mid,temp);
//向右递归进行分解
sort(array,mid+1,right,temp);
//合并
union(array,left,mid,right,temp);
}
}
public static void union(int array[],int left,int mid,int right,int temp[]){
//System.out.println(left+","+right);
// 初始化i, 左边有序序列的初始索引
int i=left;
//初始化j, 右边有序序列的初始索引
int j=mid+1;
// 指向temp数组的当前索引
int t=0;
//(一)
//先把左右两边(有序)的数据按照规则填充到temp数组
//直到左右两边的有序序列,有一边处理完毕为止
while(i<=mid&&j<=right){
if(array[i]<=array[j]){
temp[t]=array[i];
t++;
i++;
}else{
temp[t]=array[j];
t++;
j++;
}
}
//(二)
//把有剩余数据的一边的数据依次全部填充到temp
while(i<=mid){
temp[t]=array[i];
t++;
i++;
}
while(j<=right){
temp[t]=array[j];
j++;
t++;
}
//(三)
//将temp数组的元素拷贝到arr
//注意,并不是每次都拷贝所有
t=0;
int tempLeft=left;
//第一次合并 tempLeft = 0 , right = 1 // tempLeft = 2 right = 3 // tL=0 ri=3
//最后一次 tempLeft = 0 right = 7
while(tempLeft<=right){
array[tempLeft]=temp[t];
tempLeft++;
t++;
}
}
public static void main(String[] args) {
int array[]={8,4,5,7,1,3,6,2};
int temp[]=new int[array.length];
sort(array,0,array.length-1,temp);
System.out.println(Arrays.toString(array));
//0,1
//2,3
//0,3
//4,5
//6,7
//4,7
//0,7
//[1, 2, 3, 4, 5, 6, 7, 8]
int big[] = new int[80000];
for (int i = 0; i < big.length; i++) {
big[i] = (int) (Math.random() * 8000000);
}
int temp2[]=new int[big.length];
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateToStr = simpleDateFormat.format(date);
System.out.println("before sort: " + dateToStr);
sort(big, 0, big.length - 1,temp2);
Date date2 = new Date();
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateToStr2 = simpleDateFormat2.format(date2);
System.out.println("after sort: " + dateToStr2);
//[1, 2, 3, 4, 5, 6, 7, 8]
//before sort: 2020-08-10 13:57:45
//after sort: 2020-08-10 13:57:45
}
}
排序法 | 平均时间 | 最差情形 | 稳定度 | 额外空间 | 备注 | 80000随机数排序时间(s) |
---|---|---|---|---|---|---|
冒泡 | O(n²) | O(n²) | 稳定 | O(1) | n小时较好 | 13 |
选择 | O(n²) | O(n²) | 不稳定 | O(1) | n小时较好 | 4 |
插入 | O(n²) | O(n²) | 稳定 | O(1) | 大部分已排序时较好 | 2 |
希尔 | O(nlogn) | O(n的s次方) 1<s<2 | 不稳定 | O(1) | s是所选分组 | 1 |
快速 | O(nlogn) | O(n²) | 不稳定 | O(nlogn) | n大时较好 | 不到1 |
归并 | O(nlogn) | O(nlogn) | 稳定 | O(n) | n大时较好 | 不到1 |