今天调了一天程序,就是这个合并排序。合并排序主要用的就是分治法,就是将原问题分解成n个与原问题相似的小问题,利用递归的方法来解决子问题,最终将这些结果合并起来。
以下就是根据书中的伪代码用java进行的实现:(数组下标倒了一天,终于弄明白了)
public class merge_sort {
//merge-合并两个已排好序的数组
public static void merge(ArrayList<Integer> a,int p,int q,int r){
int n1 = q - p+1;
int n2 = r - q;
ArrayList<Integer> L = new ArrayList<Integer>();
ArrayList<Integer> R = new ArrayList<Integer>();
for(int i = 0;i<n1;i++){
L.add(a.get(p+i));
}
for(int i = 0;i<n2;i++){
R.add(a.get(q+i+1));
}
L.add(L.size(), Integer.MAX_VALUE);
R.add(R.size(), Integer.MAX_VALUE);
int i = 0 ;
int j = 0 ;
for(int k = p;k<r+1;k++){
if(L.get(i)>R.get(j)){
a.set(k, R.get(j));
j=j+1;
}else{
a.set(k, L.get(i));
i=i+1;
}
System.out.print(a.get(k)+" ");
}
System.out.println("");
}
//合并算法的递归
public static void mergeSort(ArrayList<Integer> a, int p , int r){
if(p<r){
int q = (r+p)/2;
mergeSort(a,p,q);
mergeSort(a,q+1,r);
merge(a,p,q,r);
}
}
public static void main(String[] args) {
// 测试合并排序
ArrayList<Integer> a = new ArrayList<Integer>();
//从控制台获取要排序的数,“#”键结束
Scanner sc = new Scanner(System.in);
while(sc.hasNextInt()){
if(sc.equals("#")){
break;
}
a.add(sc.nextInt());
}
mergeSort(a,0,a.size()-1);
}
}
递归算法(感觉是个难点)总是看起来很容易理解,但是细细看去,思路需要很清晰才不会出错。还有要说的是合并算法的时间复杂度是,在规模足够大的情况下,合并排序要比插入排序运行的时间短。
如果不使用哨兵元素,合并算法的实现方法如下:
//merge-合并两个已排好序的数组(不使用哨兵元素)
public static void merge_noguard(ArrayList<Integer> a,int p,int q,int r){
int n1 = q - p+1;
int n2 = r - q;
ArrayList<Integer> L = new ArrayList<Integer>();
ArrayList<Integer> R = new ArrayList<Integer>();
for(int i = 0;i<n1;i++){
L.add(a.get(p+i));
}
for(int i = 0;i<n2;i++){
R.add(a.get(q+i+1));
}
int i = 0 ;
int j = 0 ;
int c = p ;
while(i<n1&&j<n2){
if(L.get(i)<R.get(j)){
a.set(c, L.get(i));
i++;
}else{
a.set(c, R.get(j));
j++;
}
c++;
}
while(i<n1){
a.set(c, L.get(i));
i++;
c++;
}
while(j<n2){
a.set(c, R.get(j));
j++;
c++;
}
for(Integer integer:a){
System.out.print(integer + " ");
}
System.out.println("");
}