归并排序
采用分治法,将已有序的子序列合并,得到完全有序的序列。即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
//合并两个有序数组
public static void merge(int[] array,int low,int mid,int high){
int[] tmp = new int[high-low+1];
int k = 0;//数组下标
int s1 = low;
int e1 = mid;
int s2 = mid+1;
int e2 = high;
while (s1 <= e1 && s2 <= e2){
if (array[s1] <= array[s2]){
tmp[k++] = array[s1++];
}else {
tmp[k++] = array[s2++];
}
}
while (s1 <= e1){
tmp[k++] = array[s1++];
}
while (s2 <= e2){
tmp[k++] = array[s2++];
}
for (int i = 0; i < tmp.length; i++) {
array[i+low] = tmp[i];
}
}
//递归mid的左边和右边,合并
public static void mergeSortRec(int[] array,int low,int high){
if (low >= high){
return;
}
int mid = (high+low)/2;
mergeSortRec(array, low, mid);
mergeSortRec(array,mid+1,high);
merge(array,low,mid,high);
}
public static void mergeSort(int[] array){
mergeSortRec(array,0,array.length-1);
}
性能分析:
- 时间复杂度:O(n*logn)
- 空间复杂度:O(n)
- 稳定性:稳定
海量数据的排序问题
内部排序:将数据都存储到内存上
外部存储:数据在外存上排序的(例如磁盘)
- 切割文件,是的每个文件中的数据很小
- 读取文件中的数据,在内存上进行排序后放回
- 对这些文件进行归并(内存上两个文件一次只读一个数据来比较大小,因此不用担心归并时内存不够)