我正在尝试合并排序列表,但出现ArrayOutOfBoundsError且无法修复它。
这是使用Comparator接口的通用列表的。现在,我正在使用Integer进行测试。
这是我的合并排序类:
public class ListMS<T> {
private List<T> wholeList;
private Comparator<T> comparator;
public ListMS(List<T> list, Comparator<T> C){
wholeList=new ArrayList<>();
wholeList.addAll(list);
comparator=C;
mergeSort(wholeList, comparator);
}
public static <T> void merge(List<T> L1, List<T> L2,List<T> L, Comparator<T> C){
int i=0;
int j=0;
while(i+j<L.size()){
if(j==L2.size() || (i<L.size() && C.compare(L1.get(i),L2.get(j))<0)){
L.set(i+j,L1.get(i++));
}
else{
L.set(i+j,L2.get(j++));
}
}
}
public static <T> void mergeSort(List<T> L, Comparator<T> C){
int size=L.size();
if(size<2){
return;
}
int half=size/2;
List<T> L1=L.subList(0,half);
List<T> L2=L.subList(half,size);
mergeSort(L1,C);
mergeSort(L1,C);
merge(L1,L2,L,C);
}
public List<T> getWholeList(){
return wholeList;
}
}
我正在测试的东西:
public static void main(String[] args) {
Comparator<Integer> C=new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
List<Integer> list1K=generateList(1000);
ListMS<Integer> list1KMerged=new ListMS<>(list1K, C);
printList(list1K);
printList(list1KMerged.getWholeList());
}
public static List<Integer> generateList(int size){
List<Integer> listNumber=new ArrayList<>();
for(int i=0;i<size;i++){
int min=0;
int max=size-1;
int num=(int)(Math.random() * ((max - min) + 1)) + min;
listNumber.add(num);
}
return listNumber;
}
public static void printList(List<Integer> L){
for(int i=0;i<L.size();i++){
System.out.print(L.get(i));
}
}
但是我得到多个ArrayOutOfBounds:
线程“主”中的异常java.lang.IndexOutOfBoundsException:索引: 1,尺寸:1 at java.util.ArrayList $ SubList.rangeCheck(ArrayList.java:1225)在 java.util.ArrayList $ SubList.get(ArrayList.java:1042)在 ListMS.mergeSort(ListMS.java:40)处的ListMS.merge(ListMS.java:19) ListMS.mergeSort(ListMS.java:37)上的ListMS.mergeSort(ListMS.java:37) 在ListMS.mergeSort(ListMS.java:37)在 ListMS.mergeSort(ListMS.java:37)上的ListMS.mergeSort(ListMS.java:37) 在ListMS.mergeSort(ListMS.java:37)在 ListMS.mergeSort(ListMS.java:37)上的ListMS.mergeSort(ListMS.java:37) 在ListMS。(ListMS.java:11)在 TestListMS.main(TestListMS.java:16)
答案 0 :(得分:1)
基本上,这一行的merge()方法中的循环计数器有错误:
if(j == L2.size() || (i < L.size() && C.compare(L1.get(i), L2.get(j)) < 0))
如此修改合并功能,它将起作用:
public static <T> void merge(List<T> L1, List<T> L2,List<T> L, Comparator<T> C){
int i=0;
int j=0;
int k=0;
while(i < L1.size() && j < L2.size()) {
if(C.compare(L1.get(i), L2.get(j)) < 0) {
L.set(k++, L1.get(i++));
}else {
L.set(k++, L2.get(j++));
}
}
while(i < L1.size()) {
L.set(k++, L1.get(i++));
}
while(j < L2.size()) {
L.set(k++, L2.get(j++));
}
}
更新:
mergeSort函数中也存在多个错误。如此更改:
public static <T> void mergeSort(List<T> L, Comparator<T> C){
int size=L.size();
if(size<2){
return;
}
int half=size/2;
List<T> L1=new ArrayList<T>(L.subList(0,half));
List<T> L2=new ArrayList<T>(L.subList(half,size));
mergeSort(L1,C);
mergeSort(L2,C);
merge(L1,L2,L,C);
printList(L);
}
L1和L2在旧代码中不是新的数组列表。它们只是指向与列表L中相同的内存位置的两个指针。因此,在合并功能中修改L也会修改L1和L2。为了解决这个问题,您需要创建两个具有单独内存分配的新子数组。
您还两次调用mergeSort(L1,C);
,而不是分别在L1和L2上调用它。