归并排序的同样是采用分治思想实现的一种优秀排序算法,它的主要思路是将一个大问题分成若干小问题,然后将小问题得出的结果依次合并,得出最后大问题的解。
该算法需要一个长度为n的辅助空间,所以空间复杂度为O(n),时间复杂度为O(nlogn),是一种稳定的排序算法。对了,排序算法是否稳定,取决于相同的key值在排序前后的位置是否发生改变。
归并排序的实现较为复杂,需要两个辅助函数。首先是一个将两个有序序列归并为一个有序序列的函数。
// 将两个有序序列归并为一个有序序列
// r为有两段有序序列的数组,order为新有序序列数组
//h为第一个有序序列的起始下标,m为终止下标,t为第二个有序序列的终止下标
public static void merge(int [] r,int [] order,int h,int m,int t){
int k = h;
int i = h;
int j = m+1;
// 依次比较前后两序列的大小,小的放入order数组中
while(i<=m&&j<=t)
{
if (r[i]<r[j]) {
order[k] = r[i];
k++;
i++;
}
else {
order[k] = r[j];
k++;
j++;
}
}
// 将剩下的元素复制到order数组中
while (i<=m) {
order[k] = r[i];
k++;
i++;
}
while (j<=t) {
order[k] = r[j];
k++;
j++;
}
}
// 测试算法实现
// public static void main(String args[]){
// int [] a = {52,39,56};
// int [] b = new int [a.length];
// merge(a,b,0,0,2);
// for (int j = 0; j < b.length; j++) {
// System.out.print(b[j]);
// }
// }
一趟归并排序算法
// 一次归并排序
// s为有序序列的长度,每归并一次加倍
public static void merges(int [] r,int[] order, int s){
int p = 0;
while(p+2*s-1<=r.length-1){
merge(r, order, p, p+s-1,p+2*s-1);
p = p+2*s;
}
// 归并最后两个长度不等的有序表
if (p+s-1<r.length-1) {
merge(r, order, p, p+s-1, r.length-1);
}
// 将剩余的数据复制到order中
else {
for (int i = p; i <= r.length-1; i++) {
order[i] = r[i];
}
}
}
// 测试算法
// public static void main(String [] args){
// int [] a = {52,39,67,95,70,8,25,52,56};
// int [] b = new int [a.length];
// merges(a,b,1);
// for (int i = 0; i < b.length; i++) {
// System.out.print(b[i]+" ");
// }
// }
实现归并算法
// 实现归并排序
public static int [] mergesort(int [] r){
int s = 1;
int [] order = new int [r.length];
while (s<r.length) {
// 一次归并后,order由子有序序列组成,r为非有序序列
merges(r, order, s);
s = 2*s;
// 以order为目标序列,再归并到r
merges(order, r, s);
s = 2*s;
}
return r;
}
// 测试
public static void main(String [] args){
int [] a = {52,39,67,95,70,8,25,52,56};
int [] b = mergesort(a);
for (int i = 0; i < b.length; i++) {
System.out.print(b[i]+" ");
}
}