【问题标题】:Why won't this mergeSort work?为什么这个 mergeSort 不起作用?
【发布时间】:2015-04-26 17:34:39
【问题描述】:

好的,我的程序的这一点的目的是接收一个未排序的对象数组列表,并根据每个对象中的 getRaised() 方法对其进行排序,该方法使用递归 mergeSort 方法返回一个整数。程序运行正常,但没有对数组列表进行排序。

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));
    }

}

这是整个班级:

import java.util.ArrayList;

public class Donation {
  protected static ArrayList<Runner> Runners = new ArrayList<Runner>();
  public Donation(ArrayList<Runner> runners){
    for(int i = 0; i < runners.size(); i++){
        Runners.add(runners.get(i));
    }       
    mergeSort(Runners, 0,Runners.size()-1);
}

public void addRunner(String n, String id, double r){
    Runners.add(new Runner(n, id, r));
}
public String displayInfo(int index){
    String str = Runners.get(index).toString();
    return str;
}
public void addDonations(int index, double amt){
    Runners.get(index).Raised+=amt;
}
public double getSum(){
    double sum=0;
    for(int i = 0; i < Runners.size(); i++){
        sum+=Runners.get(i).Raised;
    }
    return sum;
}
public ArrayList<Runner> getRunnerObj(){
    return Runners;
}
public String goldenSneaker(){
    String gold = "";

    return gold;
}
public String silverSneaker(){
    String silver = "";

    return silver;
}
public String bronzeSneaker(){
    String bronze = "";

    return bronze;
}
public String achillesHeel(){
    String ach = "";

    return ach;
}

public void writeToFile(){

}

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);
        merge2(runners, min, mid, max);
    }
}

public static void merge2(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;
    int index = 0;

    for(int i = first; i <=last; 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(f2));
        f2++;
        index++;
    }

    index = 0;
    for(int i = first; i<=last;i++){
        runners.set(i,temp.get(index));
        index++;
    }
  }
}

【问题讨论】:

  • 你会得到什么?原始的未排序列表?
  • 你真的需要这个 temp = runners;在合并方法中?
  • 是的。信息是从文本文件中读入的,其中信息按不同的属性排序。因此,在所有意图和目的上,信息都是未分类的。我想按金额属性对其进行排序,该属性由 getRaised() 方法访问。
  • Uma:我的意思是删除它,这是一次失败的修复尝试
  • 为了记录,你的两行ArrayList&lt;...&gt; temp = ...;temp = runners;可以缩短为ArrayList&lt;...&gt; temp = runners

标签: java sorting recursion mergesort


【解决方案1】:

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

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&lt;Runner&gt; 更改为ArrayList&lt;Integer&gt; 对其进行了测试,它可以工作。

【讨论】:

  • Eran:那也没用。
  • @MitchellGrayEdwards 是的,这只是错误之一。见编辑。
  • 那还是没做... :/
  • 这种排序所在的类有一个名为 Runners 的全局数组列表,它是属性之一。排序是在类构造函数中调用的,该构造函数将这个 arrayList 作为参数传递。我不知道这是否澄清。但我觉得mergeSort 正在排序,但没有对类属性进行排序。就像它正在排序一样,但是什么也没发生。
  • @MitchellGrayEdwards 好吧,当我在 ArrayList&lt;Integer&gt; 上运行它时,它对我有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 2013-03-10
  • 1970-01-01
  • 2014-01-01
  • 2013-11-14
相关资源
最近更新 更多