我最近一直致力于更好地理解排序算法及其与不同类型输入的关系。目前,我正在开展一项学生管理计划,每个学生都有三个参数:姓氏,GPA和用户ID(String,double,int)。它们各自存储在具有这三个参数的Student类中,并且有DOZENS学生(该程序的一个关键特征是输入,删除和更新学生)。
我的问题是:使用主要排序算法(mergesort,quicksort等),按每个参数排序学生列表的最佳方法是什么?例如,执行mergesort以按GPA对列表进行排序的最佳方法是什么?或者使用quicksort按姓氏对列表进行排序?
基本上我的问题归结为......我可以对这些对象进行排序,如果它们没有三个参数(编写一个mergesort来排序100个数字对我来说非常容易)。如何管理其他两个参数并确保在排序后可以访问它们?
答案 0 :(得分:5)
在Java中完成此操作的方法是使用不同的Comparators。然后你说:
Collections.sort(list, new NameComparator());
或者
Collections.sort(list, new GpaComparator());
这些比较器使用不同的字段来定义两个元素之间的顺序。
例如,Name Comparator可能是:
class NameComparator implements Comparator< Student> {
@Override public int compare(Student left, Student right) {
return left.getName().compareTo(right.getName());
}
}
GpaComparator可能
class GpaComparator implements Comparator< Student> {
@Override public int compare(Student left, Student right) {
if (left.getGpa() < right.getGpa()) {
return -1;
} else if (left.getGpa() > right.getGpa()) {
return 1;
} else {
return 0;
}
}
答案 1 :(得分:1)
我建议您在Comparable
类中实施Student
界面,如下所示
public class Student implements Comparable {
public int compareType; //you can make this an enum if you want
...
public int compareTo(Object o) {
if(compareType == 0)
return gpaCompareTo(o);
else if(compareType == 1)
return nameCompareTo(o);
return idCompateTo(o);
}
public int gpaCompareTo(Object o) {
//implement your gpaCompareTo
}
public int nameCompareTo(Object o) {
//implement your nameCompareTo
}
public int idCompareTo(Object o) {
//implement your idCompareTo
}
}
然后使用像
这样的内置排序List<Student> list = new ArrayList<Student>();
...
Collections.sort(list);
或者你无法实现Comparable
并设计自己的比较器
public class MyComparator implements Comparator<Student> {
public int compare(Student o1, Student o2) {
//implement the comparator
}
public boolean equals(Object o) {
//implement the equals
}
}
然后您可以使用其他Collection's
排序方法
Collections.sort(list, MyComparator);
答案 2 :(得分:1)
执行此操作的典型方法是在接受Comparator
的任何类型上编写通用排序算法,然后编写不同的Comparator
以按不同字段排序。
答案 3 :(得分:1)
这可能是偏离主题的,但如果你想尝试一些很酷的东西,JDK 8 Lambda Preview提供了一些使用Lamda expressions and method references来定义比较器的很酷的方法。
我们说我们有一个班级:
class Jedi {
private final String name;
private final int age;
//...
}
然后是他们的集合:
List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30));
sort(jediAcademy, (j1, j2) -> j1.getAge() > j2.getAge() ? 1 : j1.getAge() < j2.getAge() ? -1 : 0);
System.out.println(jediAcademy); //Anakin, Obiwan
或者使用方法引用,假设Jedi具有表现为比较器(相同签名)的方法
class Jedi {
public static int compareByAge(Jedi first, Jedi second){
return first.age > second.age ? 1 : first.age < second.age ? -1 : 0;
}
//...
}
可以使用以下方法通过使用方法引用来生成比较器:
List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30));
sort(jediAcademy, Jedi::compareByAge);
System.out.println(jediAcademy);//Anakin, Obiwan
答案 4 :(得分:0)
与排序数字没有什么不同,除了在这种情况下你的&#34;数字&#34;用户的三个字段,每个数字的值受每个字段的值约束,字段的顺序决定了排序排名。
更具体一点,你有一个包含3个字段的Tupple:<GPA, Last Name, User ID>
,并假设您要按GPA排序,然后按姓氏和用户ID排序。
与219在139以上排序的方式相同(即&#34;数百&#34;数字具有更高的值,即使&#34;数字&#34;数字更低),类似于{ {1}}将排在<3.75, Jones, 5>
之上,因为&#34; GPA数字&#34; (更重要的是)具有更高的价值,即使&#34;姓氏数字&#34;较低(例如琼斯比亚当斯低#34;)
答案 5 :(得分:0)
使用多个比较器
class Student
{
String lastName;
dounle GPA;
int userId
static Comparator<Student> getStudentLastNameComparator() {
return new Comparator<Student>() {
@Override
public int compare(Student Student1, Student Student2) {
return Student1.getlastName().compareTo(Student2.getlastName());
}
// compare using Student lastName
};
}
static Comparator<Student> getStudentGPAComparator() {
return new Comparator<Student>() {
@Override
public int compare(Student Student1, Student Student2) {
if(Student1.GPA < Student2.GPA)
return 1;
else
return -1;
}
// compare using Student GPA
};
}
static Comparator<Student> getStudentUserIdComparator() {
return new Comparator<Student>() {
@Override
public int compare(Student Student1, Student Student2) {
if(Student1.userId < Student2.userId)
return 1;
else
return -1;
}
// compare using Student userId
};
}
}