如何在java中使用泛型实现递归mergeSort?

时间:2015-04-08 15:06:06

标签: java generics recursion mergesort

我正在实现mergeSort功能。我理解分而治之的逻辑,但实际的合并部分令我感到困惑。这是过去的作业问题,但我试图理解它。

       /**
         * Implement merge sort.
         *
         * It should be:
         * stable

         * Have a worst case running time of:
         *  O(n log n)
         *
         * And a best case running time of:
         *  O(n log n)
         *
         * You can create more arrays to run mergesort, but at the end,
         * everything should be merged back into the original T[]
         * which was passed in.
         *
         * ********************* IMPORTANT ************************
         * FAILURE TO DO SO MAY CAUSE ClassCastException AND CAUSE
         * YOUR METHOD TO FAIL ALL THE TESTS FOR MERGE SORT
         * ********************************************************
         *
         * Any duplicates in the array should be in the same relative position      
         * after sorting as they were before sorting.
         *
         * @throws IllegalArgumentException if the array or comparator is null
         * @param <T> data type to sort
         * @param arr the array to be sorted
         * @param comparator the Comparator used to compare the data in arr
         */

对于此方法,无法更改参数,public,static和泛型。我不知道如何进行递归合并功能。

public static <T> void mergesort(T[] arr, Comparator<T> comparator) {
    if (arr == null || comparator == null) {
        throw new IllegalArgumentException("Null arguments were passed.");
    }
    if (arr.length >= 2) {
        //Midpoint from which we will split the array.
        int middle = arr.length / 2;
        //Each half of the split array
        T[] left = (T[]) new Object[middle];
        T[] right = (T[]) new Object[arr.length - middle];
        //Copy items from original into each half
        for (int i = 0; i < middle; i++) {
            left[i] = arr[i];
        }
        for (int i = middle; i < length; i++) {
            right[i] = arr[i];
        }
        //Keep splitting until length is 1
        mergesort(left, comparator);
        mergesort(right, comparator);
        //merge each array back into original which would now be sorted.
        merge(left, right, middle, arr, comparator);
        merge(right, middle, arr, comparator);

    }

}

private static <T> T[] merge(T[] left, T[] right, int middle, T[] arr,
                             Comparator<T>
        comparator) {
    int i = 1, j = middle + 1, k = 1;
    while (i <= middle && j <= arr.length) {
        arr[k++] = (comparator.compare(arr[k], partioned[i]) < 0)
                ? arr[j++] : partioned[i++];
    }
    while (i <= middle) {
        arr[k++] = partioned[k++];
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个可能的解决方案。我不记得是否有更好的方法,因为我通常只使用Collections.sort()。

请注意,不需要返回值,因为原始数组的内容将被修改。

也没有必要传递中间索引。

private static <T> void merge(T[] left, T[] right, T[] dest) {
  if (left.length + right.length != dest.length)
    throw new IllegalArgumentException(
                    "left length + right length must equal destination length");
  int leftIndex = 0;
  int rightIndex = 0;
  int destIndex = 0;
  while (destIndex < dest.length) {
    if (leftIndex >= left.length) //no more entries in left array, use right
      dest[destIndex++] = right[rightIndex++];
    else if (rightIndex >= right.length) // no more entries in right array, use left
      dest[destIndex++] = left[leftIndex++];
    else if (left[leftIndex] < right[rightIndex]) //otherwise pick the lower value
      dest[destIndex++] = left[leftIndex++];
    else 
      dest[destIndex++] = right[rightIndex++];
  }
}