为什么这个mergeSort不会工作?

时间:2015-04-26 17:34:40

标签: java sorting recursion mergesort

好的,我的程序的这一部分的目的是获取一个未排序的对象数组列表,并根据每个对象中的getRaised()方法对其进行排序,该方法使用递归mergeSort方法返回一个整数。程序运行时没有错误,但它没有对arraylist进行排序。

click div.btn-group

这是整个班级:

public static void mergeSort(ArrayList<Runner> runners, int min, int max){
    if(min < max){
        int mid = (min+max)/2;
        mergeSort(runners, min, mid);
        mergeSort(runners, mid+1, max);
        merge(runners, min, mid, max);
    }
}
public static void merge(ArrayList<Runner> runners, int first, int mid, int last){
    ArrayList<Runner> temp = new ArrayList<>();
    temp = runners;
    int f1 = first;
    int l1 = mid;
    int f2 = mid+1;
    int l2 = last;
    int index = f1;

    for(int i = 0; i < runners.size(); i++){
        temp.add(runners.get(i));
    }

    while(f1 <= l1 && f2 <= l2){
        if(runners.get(f1).getRaised() < runners.get(f2).getRaised()){
            temp.set(index, runners.get(f1));
            f1++;
        }else{
            temp.set(index, runners.get(f2));
            f2++;
        }
        index++;
    }
    while(f1 <= l1){
        temp.set(index, runners.get(f1));
        f1++;
        index++;
    }
    while(f2<=l2){
        temp.set(index, runners.get(f1));
        f2++;
        index++;
    }
    for(int i = 0; i<=runners.size();i++){
        runners.set(i,temp.get(index));
    }

}

1 个答案:

答案 0 :(得分:0)

您的合并方法有多处错误:

public static void merge(ArrayList<Runner> runners, int first, int mid, int last){
    ArrayList<Runner> temp = new ArrayList<>();
    temp = runners; // remove that line, otherwise your original list will
                    // continue growing until you run out of memory
    int f1 = first;
    int l1 = mid;
    int f2 = mid+1;
    int l2 = last;
    int index = f1;

    for(int i = 0; i < runners.size(); i++){
        temp.add(runners.get(i));
    }

    while(f1 <= l1 && f2 <= l2){
        if(runners.get(f1).getRaised() < runners.get(f2).getRaised()){
            temp.set(index, runners.get(f1));
            f1++;
        }else{
            temp.set(index, runners.get(f2));
            f2++;
        }
        index++;
    }
    while(f1 <= l1){
        temp.set(index, runners.get(f1));
        f1++;
        index++;
    }
    while(f2<=l2){
        temp.set(index, runners.get(f1)); // typo - should be get(f2)
        f2++;
        index++;
    }
    for(int i = 0; i<=runners.size();i++){ // should be i<runners.size()
                                           // to avoid index out of bounds
                                           // exception
        runners.set(i,temp.get(index)); // should be i instead of index
    }

}

这样可行,但效率不高,因为在每次调用merge时,您将整个源列表复制到临时列表并返回到源列表,而应该复制的唯一索引是从头到尾的指数。

这是一个更有效的合并:

public static void merge(ArrayList<Runner> runners, int first, int mid, int last){
    ArrayList<Runner> temp = new ArrayList<>();
    int f1 = first;
    int l1 = mid;
    int f2 = mid+1;
    int l2 = last;

    while(f1 <= l1 && f2 <= l2){
        if(runners.get(f1).getRaised() < runners.get(f2).getRaised()){
            temp.add(runners.get(f1));
            f1++;
        }else{
            temp.add(runners.get(f2));
            f2++;
        }
    }
    while(f1 <= l1){
        temp.add(runners.get(f1));
        f1++;
    }
    while(f2<=l2){
        temp.add(runners.get(f2));
        f2++;
    }

    // copy only the merged range back to runners
    int index = 0;
    for(int i = first; i<=last;i++){
        runners.set(i,temp.get(index));
        index++;
    }

}

我通过将ArrayList<Runner>更改为ArrayList<Integer>来测试它,但它确实有效。