结束了快速排序学习之后,对其分段排序的思想的延续便是归并排序。
归并排序是一种稳定的排序算法。
时间复杂度:O(nlogn) ,空间复杂度:O(n),是一种典型的空间换时间的算法。
原理: 归并排序将待排序的元素序列分成两个长度相等的子序列,为每一个子序列排序,然后再将他们合并成一个子序列。合并两个子序列的过程也就是归并。
盗用一张图:
代码实现
import java.util.Arrays;
/**
* 归并排序
* @author scz
*/
public class MergeSort {
//两路归并算法,两个排好序的子序列合并为一个子序列
public static void merge(int []a,int left,int mid,int right){
int []tmp=new int[a.length];//辅助数组
int p1=left,p2=mid+1,k=left;//p1、p2是检测指针,k是存放指针
while(p1<=mid && p2<=right){
if(a[p1]<=a[p2])
tmp[k++]=a[p1++];
else
tmp[k++]=a[p2++];
}
while(p1<=mid) tmp[k++]=a[p1++];//如果第一个序列未检测完,直接将后面所有元素加到合并的序列中
while(p2<=right) tmp[k++]=a[p2++];//同上
//复制回原素组
for (int i = left; i <=right; i++)
a[i]=tmp[i];
}
public static void mergeSort(int [] a,int start,int end){
if(start<end){//当子序列中只有一个元素时结束递归
int mid=(start+end)/2;//划分子序列
mergeSort(a, start, mid);//对左侧子序列进行递归排序
mergeSort(a, mid+1, end);//对右侧子序列进行递归排序
merge(a, start, mid, end);//合并
}
}
public static void main(String[] args){
int[] a = {5,4,7,6,2,8};
mergeSort(a, 0, a.length-1);
System.out.println(Arrays.toString(a));
}
}
相比于快速排序,归并排序在数据量极为巨大时具有时间上的优势,数据量巨大,会很容易使快速排序进入最坏情况退化成冒泡排序,而归并排序时间复杂度无论好坏都为O(nlogn) 。