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的最大值来表示,这点可能会有隐患,不过还好有不需要哨兵牌的表达方式,虽然写起来稍微有点麻烦
没想到写算法也会让人沉迷.
睡了