简体   繁体   English

如何使用Java接口比较器进行通用合并排序?

[英]How to do a Generic Merge Sort with the Java Interface Comparator?

I'm trying to merge sort lists but get ArrayOutOfBoundsError and don't manage to fix it. 我正在尝试合并排序列表,但是得到ArrayOutOfBoundsError,并且无法修复它。

This is for generic Lists using the Comparator interface. 这是针对使用Comparator接口的通用列表的。 For now I'm running test with Integer. 现在,我正在使用Integer进行测试。

This is my merge sort class: 这是我的合并排序类:

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

What I'm testing it with: 我正在用什么进行测试:

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

But I get multiple ArrayOutOfBounds: 但我得到多个ArrayOutOfBounds:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 at java.util.ArrayList$SubList.rangeCheck(ArrayList.java:1225) at java.util.ArrayList$SubList.get(ArrayList.java:1042) at ListMS.merge(ListMS.java:19) at ListMS.mergeSort(ListMS.java:40) at ListMS.mergeSort(ListMS.java:37) at ListMS.mergeSort(ListMS.java:37) at ListMS.mergeSort(ListMS.java:37) at ListMS.mergeSort(ListMS.java:37) at ListMS.mergeSort(ListMS.java:37) at ListMS.mergeSort(ListMS.java:37) at ListMS.mergeSort(ListMS.java:37) at ListMS.mergeSort(ListMS.java:37) at ListMS.(ListMS.java:11) at TestListMS.main(TestListMS.java:16) 线程“主”中的异常java.lang.IndexOutOfBoundsException:索引:1,大小:1在java.util.ArrayList $ SubList.rangeCheck(ArrayList.java:1225)在java.util.ArrayList $ SubList.get(ArrayList.java) :1042)在ListMS.merge(ListMS.java:19)在ListMS.mergeSort(ListMS.java:40)在ListMS.mergeSort(ListMS.java:37)在ListMS.mergeSort(ListMS.java:37)在ListMS。在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)

Basically, there is an error in your loop counters in merge() methid at this line: 基本上,这行的merge()方法中的循环计数器有错误:

if(j == L2.size() || (i < L.size() && C.compare(L1.get(i), L2.get(j)) < 0))

Modify the merge function as so, it will work: 修改合并功能,它将起作用:

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

UPDATE: 更新:

There are multiple errors in mergeSort function as well. mergeSort函数中也存在多个错误。 Change it as so: 如此更改:

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 and L2 were not new array-list in old code. L1和L2在旧代码中不是新的数组列表。 They were just two pointers pointing to same memory locations as in the List L. So modifying L in merge function also modified L1 and L2. 它们只是指向与列表L中相同的内存位置的两个指针。因此,在合并功能中修改L也会修改L1和L2。 In order to solve this, you need to create two new subarrays with separate memory allocations. 为了解决这个问题,您需要创建两个具有单独内存分配的新子数组。

Also you were calling mergeSort(L1,C); 您还调用了mergeSort(L1,C); twice instead of calling it on L1 and L2 each. 两次,而不是分别在L1和L2上调用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM