您的位置:首页 > 编程语言 > Java开发

归并排序【Java实现】

2016-12-17 16:22 381 查看

 归并排序(Merge Sort)

基本思想:

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序示例:

 


合并方法:

设r[i…n]由两个有序子表r[i…m]和r[m+1…n]组成,两个子表长度分别为n-i +1、n-m。

j=m+1;k=i;i=i; //置两个子表的起始下标及辅助数组的起始下标
若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束
//选取r[i]和r[j]较小的存入辅助数组rf

如果r[i]<r[j],rf[k]=r[i]; i++; k++; 转⑵

否则,rf[k]=r[j]; j++; k++; 转⑵
//将尚未处理完的子表中元素存入rf

如果i<=m,将r[i…m]存入rf[k…n] //前一子表非空

如果j<=n ,  将r[j…n] 存入rf[k…n] //后一子表非空
合并结束。

/*
* 两个有序子列的归并,两个子列的长度都相等,为length
* 两个有序子列归并后,存入在数组temp中
*/
public static void merge(int[] a,int[] temp,int length,int l,int r){
int begin = l;
int leftend = r -1;
int rightend = r+length-1;
while(l<=leftend && r<=rightend){
if(a[l] > a[r]){
temp[begin++] = a[r++];
}else{
temp[begin++] = a[l++];
}
}
while(r<=rightend){
temp[begin++] = a[r++];
}
while(l<=leftend){
temp[begin++] = a[l++];
}
}


一个无序的序列可以采用分而治之的思想:

(1)从长度为1的子序列开始归并,则变成了都是长度为2的有序子序列;

(2)按长度为2的子序列开始归并,则变成了都是长度为4的有序子序列;

(3)。。。。

(4)归并结束。



序列归并的非递归算法

/*
* 6、归并排序
* 非递归归并实现
* 把一个序列,从0下标开始,先对1对数进行归并,然后再对2对数进行归并。。。
*/
public static void merge_sort(int[] a,int n){
int length = 1;//归并子序列的长度
int[] temp = new int
;
while(length<n){
merge_pass(a, temp, n, length);
length *= 2;
merge_pass(temp, a, n, length);
length *= 2;
}

}
/*
* 完成一躺子序列归并
* length为归并子序列的长度
*/
public static void merge_pass(int[] a,int[] temp,int n,int length){
int i = 0;
for (; i <= n-2*length; i=2*length+i) {
merge(a, temp, length, i, i+length);
}
if(i+length<n){//最后还剩下大于等于一个子列长度
merge(a, temp, n-i-length, i, i+length);
}else{//最后只剩下小于一个子列长度,则直接赋值
for (int j = i; j < n; j++) {
temp[j] = a[j];
}
}
System.out.print("子列长为"+length+"归并: ");
display(temp);
}

/* * 两个有序子列的归并,两个子列的长度都相等,为length * 两个有序子列归并后,存入在数组temp中 */ public static void merge(int[] a,int[] temp,int length,int l,int r){ int begin = l; int leftend = r -1; int rightend = r+length-1; while(l<=leftend && r<=rightend){ if(a[l] > a[r]){ temp[begin++] = a[r++]; }else{ temp[begin++] = a[l++]; } } while(r<=rightend){ temp[begin++] = a[r++]; } while(l<=leftend){ temp[begin++] = a[l++]; } }


测试代码:

  
public static void main(String[] args) {
int[] a = {3,2,4,6,11,3,34,27,2,1,22,9,45,6};
int[] temp = new int[a.length];
System.out.print("子序列归并之前: ");
display(a);
merge_sort(a, a.length);
}


结果为:

子序列归并之前: 3 2 4 6 11 3 34 27 2 1 22 9 45 6 
子列长为1归并: 2 3 4 6 3 11 27 34 1 2 9 22 6 45 
子列长为2归并: 2 3 4 6 3 11 27 34 1 2 9 22 6 45 
子列长为4归并: 2 3 3 4 6 11 27 34 1 2 6 9 22 45 
子列长为8归并: 1 2 2 3 3 4 6 6 9 11 22 27 34 45 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐