java中的通用MergeSort实现

时间:2018-06-16 17:34:19

标签: java arrays mergesort

我编写了一个MergeSort实现,它应该对任何数据类型的数组进行排序。

我在这里面临两个问题。

  1. 由于编译器出错,无法将通用类型定义为数组 说' 无法创建T '的通用数组, 我已经跟踪了StackOverflow中其中一个线程中建议的kludge使用

    T [] right =(T [])Array.newInstance(clazz,rightSize);

  2. 因此,使用运行时提供的类型信息,我们仍然可以实例化一个数组并将其强制转换回T [],尽管它仍然容易受到ClassCastException的影响,无论我们是否处理它。

    还有其他有效且理想的方法来实现这一目标吗?

    1. 现在,下面的合并排序算法基于泛型, 我无法在T []。
    2. 的位置提供像int []这样的基本类型数组

      那么我是否需要为每个我想要排序的原始类型数组创建一个MergeSort类?

      1. 一般来说,这个算法可以进一步改进吗?
      2. 非常感谢任何帮助。 感谢。

        import java.lang.reflect.Array;
        import java.util.Arrays;
        import java.util.Comparator;
        
        public class MergeSort {
        
            public <T> void sort(T[] values, Class<T> clazz, Comparator<T> comparator) {
                if (values == null) {
                    throw new IllegalArgumentException("values is null.");
                }
        
                // recursion exit criteria.
                if (values.length < 2) {
                    return;
                }
        
                // segregate the values array into 2 halves.
                int median = values.length / 2;
                int leftSize = median;
                int rightSize = values.length - median;
        
                // construct the left array.
                T[] left = (T[]) Array.newInstance(clazz, leftSize);
                for (int l = 0; l < leftSize; ++l) {
                    left[l] = values[l];
                }
        
                // construct the right array.
                T[] right = (T[]) Array.newInstance(clazz, rightSize);
                for (int r = 0; r < rightSize; ++r) {
                    right[r] = values[leftSize + r];
                }
        
                // recursively do merge sort on either side of the array.
                sort(left, clazz, comparator);
                sort(right, clazz, comparator);
        
                // merges the left and right and keeps the intermediate
                // values array sorted as it works it's way up.
                _merge(values, left, right, comparator);
        
            }
        
            private <T> void _merge(T[] values, T[] left, T[] right, Comparator<T> comparator) {
                int leftIndex = 0;
                int rightIndex = 0;
                int sortedIndex = 0;
        
                while (leftIndex < left.length && rightIndex < right.length) {
                    int comparison = comparator.compare(left[leftIndex], right[rightIndex]);
                    if (comparison <= 0) {
                        values[sortedIndex] = left[leftIndex];
                        leftIndex++;
                    } else {
                        values[sortedIndex] = right[rightIndex];
                        rightIndex++;
                    }
                    sortedIndex++;
                }
        
                // Handle the left over elements if any in the left side
                // and places them in the sorted array.
                while (leftIndex < left.length) {
                    values[sortedIndex] = left[leftIndex];
                    leftIndex++;
                    sortedIndex++;
                }
        
                // Handle the left over elements if any in the right side.
                // and places them in the sorted array.
                while (rightIndex < right.length) {
                    values[sortedIndex] = right[rightIndex];
                    rightIndex++;
                    sortedIndex++;
                }
            }
        
            public static void main(String[] args) {
                Integer[] values = new Integer[] { 5, 0, 10, 4, 1, 8, 3, 9, 6, 2, 7 };
        
                new MergeSort().sort(values, Integer.class, new Comparator<Integer>() {
        
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        return o1.compareTo(o2);
                    }
                });
        
                System.out.println(Arrays.toString(values));
            }
        }
        

1 个答案:

答案 0 :(得分:4)

关于你的第一个问题:你可以使用

T[] newArray = (T[]) new Object[newSize];

您可以保证此演员表始终成功,新数组将始终只保留T秒。因此,铸件被整流 1 。要取消unchecked cast - 警告,请使用@SuppressWarnings("unchecked")标记方法。

关于你的第二个问题:为了获得最佳表现,是的。您应该为每种基本类型提供一个实现。协方差和自动装箱不足以将int[]转换为Integer[]

关于第三个问题:您可以实际重新使用旧数组,而不是为左右部分创建新数组,只需将左右传递作为递归调用的参数。有关实施,请参阅this github link

对代码的评论:在Java中,方法名称应始终以小写字母开头。虽然我知道在C ++中使用_启动私有方法很常见,但在Java中并非如此。

对您的问题的一些一般性评论:

  • 每个帖子你应该限制自己一个问题。
  • 如果您的代码功能正常,并且您希望获得有关代码的反馈,那么Code Review可能更适合您。

1 java.util.ArrayList使用类似的apporoach:支持数组是Object[],私有方法E elementData(int index)将返回值强制转换为{{1} }}