Java:ArrayList 的合并排序不起作用
Java: Mergesort for ArrayList does not work
它正确地比较了对象,但将包含重复对象的列表的大小加倍。
public static void mergeSort(List<Person> list) {
List<Person> helper = new ArrayList<Person>(list.size());
mergeSort(list, helper, 0, list.size());
}
private static void mergeSort(List<Person> list, List<Person> helper, int low, int high) {
if(low < high) {
int middle = (low+high)/2;
mergeSort(list, helper, low, middle); //sort left half
mergeSort(list, helper, middle+1, high); //sort right half
merge(list, helper, low, middle, high); // merge
}
}
private static void merge(List<Person> list, List<Person> helper, int low, int middle, int high) {
for(int i=low; i<= high; i++) {
helper.add(i, list.get(i));
}
int helperLeft = low;
int helperRight = middle + 1;
int current = low;
/**
* Iterate through helper array, copying back smaller element in the original list
*/
while(helperLeft <= middle && helperRight <= high) {
if(helper.get(helperLeft).isLessThan( helper.get(helperRight))) {
list.add(current, helper.get(helperLeft));
helperLeft++;
} else {
list.add(current, helper.get(helperRight));
helperRight++;
}
current++;
}
//Copy remaining elements
int remaining = middle - helperLeft;
for(int j=0; j <= remaining; j++) {
list.add(current+j, helper.get(helperLeft+j));
}
}
Person.java
public class Person implements Comparable<Person>{
private String personId;
private String month;
private String day;
private String year;
private Date personDay;
static SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
public Person(String id, String month, String day, String year) {
this.personId = id;
this.month = month;
this.day = day;
this.year = year;
}
@Override
public int compareTo(Person person) {
return this.getPersonDay().compareTo(person.getPersonDay());
}
public boolean isLessThan(Person person) {
boolean isLess = false;
if(this.getPersonDay().compareTo(person.getPersonDay()) < 0) {
isLess = true;
}
return isLess;
}
}
测试对象
List<Person> list = new ArrayList<Person>();
list.add(new Person("1L", "10", "1", "1960"));
list.add(new Person("1L", "4", "5", "1978"));
list.add(new Person("1L", "9", "17", "1986"));
list.add(new Person("1L", "2", "15", "1971"));
list.add(new Person("1L", "7", "1", "1971"));
有几个问题...
不要使用List#add
,使用List#set
而不是...
while(helperLeft <= middle && helperRight <= high) {
if(helper.get(helperLeft).isLessThan( helper.get(helperRight))) {
list.add(current, helper.get(helperLeft));
helperLeft++;
} else {
list.add(current, helper.get(helperRight));
helperRight++;
}
current++;
}
//Copy remaining elements
int remaining = middle - helperLeft;
for(int j=0; j <= remaining; j++) {
list.add(current+j, helper.get(helperLeft+j));
}
使用...
while(helperLeft <= middle && helperRight <= high) {
if (helper.get(helperLeft).isLessThan(helper.get(helperRight))) {
list.set(current, helper.get(helperLeft));
helperLeft++;
} else {
list.set(current, helper.get(helperRight));
helperRight++;
}
current++;
}
//Copy remaining elements
int remaining = middle - helperLeft;
for (int j = 0; j <= remaining; j++) {
list.set(current + j, helper.get(helperLeft + j));
}
List
s,像数组一样,是零索引的,所以不是...
for (int i = low; i <= high; i++) {
helper.add(i, list.get(i));
}
你应该使用
for (int i = low; i < high; i++) {
helper.add(i, list.get(i));
}
而不是...
while (helperLeft <= middle && helperRight <= high) {
你应该使用...
while (helperLeft < middle && helperRight < high) {
因此,在对您的示例中缺少的代码进行更正以适应之后(例如 getPersonDay
),我得到类似...
----Unsorted
1L; 10/01/1960
1L; 04/05/1978
1L; 09/17/1986
1L; 02/15/1971
1L; 07/01/1971
----Sorted
1L; 10/01/1960
1L; 02/15/1971
1L; 07/01/1971
1L; 04/05/1978
1L; 09/17/1986
当high-low<2时,忘记排序List.You这个小范围需要处理那个小case,如下
private static void mergeSort(List<Person> list, List<Person> helper, int low, int high) {
if(high - low<2) {
sortTheSmallList(list,low,high);
}else{
int middle = (low+high)/2;
mergeSort(list, helper , low, middle); //sort left half
mergeSort(list, helper, middle+1, high); //sort right half
merge(list, helper, low, middle, high);
}
}
它正确地比较了对象,但将包含重复对象的列表的大小加倍。
public static void mergeSort(List<Person> list) {
List<Person> helper = new ArrayList<Person>(list.size());
mergeSort(list, helper, 0, list.size());
}
private static void mergeSort(List<Person> list, List<Person> helper, int low, int high) {
if(low < high) {
int middle = (low+high)/2;
mergeSort(list, helper, low, middle); //sort left half
mergeSort(list, helper, middle+1, high); //sort right half
merge(list, helper, low, middle, high); // merge
}
}
private static void merge(List<Person> list, List<Person> helper, int low, int middle, int high) {
for(int i=low; i<= high; i++) {
helper.add(i, list.get(i));
}
int helperLeft = low;
int helperRight = middle + 1;
int current = low;
/**
* Iterate through helper array, copying back smaller element in the original list
*/
while(helperLeft <= middle && helperRight <= high) {
if(helper.get(helperLeft).isLessThan( helper.get(helperRight))) {
list.add(current, helper.get(helperLeft));
helperLeft++;
} else {
list.add(current, helper.get(helperRight));
helperRight++;
}
current++;
}
//Copy remaining elements
int remaining = middle - helperLeft;
for(int j=0; j <= remaining; j++) {
list.add(current+j, helper.get(helperLeft+j));
}
}
Person.java
public class Person implements Comparable<Person>{
private String personId;
private String month;
private String day;
private String year;
private Date personDay;
static SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
public Person(String id, String month, String day, String year) {
this.personId = id;
this.month = month;
this.day = day;
this.year = year;
}
@Override
public int compareTo(Person person) {
return this.getPersonDay().compareTo(person.getPersonDay());
}
public boolean isLessThan(Person person) {
boolean isLess = false;
if(this.getPersonDay().compareTo(person.getPersonDay()) < 0) {
isLess = true;
}
return isLess;
}
}
测试对象
List<Person> list = new ArrayList<Person>();
list.add(new Person("1L", "10", "1", "1960"));
list.add(new Person("1L", "4", "5", "1978"));
list.add(new Person("1L", "9", "17", "1986"));
list.add(new Person("1L", "2", "15", "1971"));
list.add(new Person("1L", "7", "1", "1971"));
有几个问题...
不要使用List#add
,使用List#set
而不是...
while(helperLeft <= middle && helperRight <= high) {
if(helper.get(helperLeft).isLessThan( helper.get(helperRight))) {
list.add(current, helper.get(helperLeft));
helperLeft++;
} else {
list.add(current, helper.get(helperRight));
helperRight++;
}
current++;
}
//Copy remaining elements
int remaining = middle - helperLeft;
for(int j=0; j <= remaining; j++) {
list.add(current+j, helper.get(helperLeft+j));
}
使用...
while(helperLeft <= middle && helperRight <= high) {
if (helper.get(helperLeft).isLessThan(helper.get(helperRight))) {
list.set(current, helper.get(helperLeft));
helperLeft++;
} else {
list.set(current, helper.get(helperRight));
helperRight++;
}
current++;
}
//Copy remaining elements
int remaining = middle - helperLeft;
for (int j = 0; j <= remaining; j++) {
list.set(current + j, helper.get(helperLeft + j));
}
List
s,像数组一样,是零索引的,所以不是...
for (int i = low; i <= high; i++) {
helper.add(i, list.get(i));
}
你应该使用
for (int i = low; i < high; i++) {
helper.add(i, list.get(i));
}
而不是...
while (helperLeft <= middle && helperRight <= high) {
你应该使用...
while (helperLeft < middle && helperRight < high) {
因此,在对您的示例中缺少的代码进行更正以适应之后(例如 getPersonDay
),我得到类似...
----Unsorted
1L; 10/01/1960
1L; 04/05/1978
1L; 09/17/1986
1L; 02/15/1971
1L; 07/01/1971
----Sorted
1L; 10/01/1960
1L; 02/15/1971
1L; 07/01/1971
1L; 04/05/1978
1L; 09/17/1986
当high-low<2时,忘记排序List.You这个小范围需要处理那个小case,如下
private static void mergeSort(List<Person> list, List<Person> helper, int low, int high) {
if(high - low<2) {
sortTheSmallList(list,low,high);
}else{
int middle = (low+high)/2;
mergeSort(list, helper , low, middle); //sort left half
mergeSort(list, helper, middle+1, high); //sort right half
merge(list, helper, low, middle, high);
}
}