您的位置:首页 > 其它

算法导论2.3MERGE-SORT(分治或者合并排序算法)

2016-09-29 22:35 260 查看
public static void main(String[] args) {
int[] s = {3, 2, 4, 5, 7, 6, 1};
//注意下标的选取,用伪代码都需要+1
sort(s,0,6);
print(s);
}

private static void  print(int[] s){
for (int i = 0; i < s.length; i++) {
if(i == 0){
System.out.print("{");
}
System.out.print(s[i]);
if(i < s.length -1){
System.out.print(",");
}
if(i ==  s.length -1){
System.out.print("}\n");
}
}
}
private static void sort(int[] s , int p ,int r){
//只要p<r说明还可以继续分解
if(p < r ){
//取不大于(p+r)/2的最大整数
int q = (p+r)/2 ;
//排序下标为p到q的元素
sort(s,p,q);
//排序下标为q+1到r的元素
sort(s,q+1,r);
//合并
sortMegre(s,p,q,r);

}
}
//哨兵牌处理子数组的结束
private static void sortMegre(int[] s , int p , int q , int r){
int n1 = q-p+1;
int n2 = r-q;
int[] L = new int[n1+1];
int[] R = new int[n2+1];
for (int i = 0; i < L.length-1; i++) {
L[i] = s[p+i];
}
for (int i = 0; i < R.length-1; i++) {
R[i] =s[q+i+1];
}
//哨兵牌
L[n1] =Integer.MAX_VALUE;
R[n2] =Integer.MAX_VALUE;
int j =0;
int k = 0;
for (int i = p; i <= r; i++) {
if(L[j] <=R[k]){
s[i] = L[j];
j++;
}else{
s[i] = R[k];
k++;
}
}
//没有哨兵牌的排序方法
private static void sortMegreNosentinal(int[] s , int p , int q , int r){
int n1 = q-p+1;
int n2 = r-q;
int[] L = new int[n1];
int[] R = new int[n2];
for (int i = 0; i < L.length; i++) {
L[i] = s[p+i];
}
for (int i = 0; i < R.length; i++) {
R[i] =s[q+i+1];
}
int j =0;
int k = 0;
int i ;
for ( i = p; i <= r; i++) {
//如果大于子数组的最大下标则说明子数组已经空了
if(j > n1-1  || k > n2-1){
break;
}
if(L[j] <=R[k]){
s[i] = L[j];
j++;
}else{
s[i] = R[k];
k++;
}

}
//左侧为空
if(j  > n1-1){
//将右侧剩余的列表赋值给s
for ( int m = 0; m < r-i+1; m++) {
s[i+m] = R[k+m];
}
}
//右侧为空
if(k > n2-1 ){
//将左侧剩余的列表赋值给s
for ( int m = 0; m < r-i+1; m++) {
s[i+m] = L[j+m];
}
}
}


注意事项详见注释吧

这个排序方法原理不是特别的麻烦

但写起来很麻烦

问题主要是在下标的处理

伪代码是从1开始

而java都是从0开始计算的

但是我觉得掌握到原理还是比较简单的

另外需要注意这里的下标p,q,r都是包含的关系,可能和我们平时写代码的习惯不一样,这是个不小的坑

哨兵牌我没有找到无穷大怎么表示,只能暂时用int的最大值来表示,这点可能会有隐患,不过还好有不需要哨兵牌的表达方式,虽然写起来稍微有点麻烦

没想到写算法也会让人沉迷.

睡了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: