簡體   English   中英

Java 中的通用 MergeSort 實現

[英]A generic MergeSort implementation in java

我編寫了一個 MergeSort 實現,它應該對任何數據類型的數組進行排序。

我在這里面臨兩個問題。

  1. 由於泛型類型不能定義為數組,因為編譯器錯誤說“無法創建 T 的泛型數組”,因此我遵循了 StackOverflow 中的一個線程中建議的 kludge 使用

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

因此,使用運行時提供的類型信息,我們仍然可以實例化一個數組並將其轉換回 T[],盡管無論我們是否處理它,它仍然容易受到 ClassCastException 的影響。

有沒有其他有效和理想的方法來實現這一目標?

  1. 現在下面的合並排序算法基於泛型工作,我不能提供像 int[] 這樣的原始類型數組來代替 T[]。

那么我是否需要為我想要排序的每個原始類型數組創建一個版本的 MergeSort 類?

  1. 總的來說,這個算法可以進一步改進嗎?

任何幫助將不勝感激。 謝謝。

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

對於您的第一個問題:您可以使用

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

您可以保證此轉換將始終成功,並且新數組將始終僅包含T s。 因此,演員陣容得到糾正1 要抑制unchecked cast強制轉換警告,請使用@SuppressWarnings("unchecked")標記該方法。 一種類似的方法是用於OpenJDK 的ArrayList實現


對於您的第二個問題:為了獲得最佳性能,是的。 您應該為每個原始類型提供一個實現。 協方差和自動裝箱不足以將int[]轉換為Integer[]


對於您的第三個問題:您可以重新使用舊數組,而不是為左右部分創建新數組,而只需將leftright作為參數傳遞left您的遞歸調用。 有關實現,請參閱此 github 鏈接


代碼注釋:在 Java 中,方法名稱應始終以小寫字母開頭。 雖然我知道在 C++ 中用_啟動私有方法是很常見的,但在 Java 中情況並非如此。


對你的問題的一些一般性評論:

  • 您應該將自己限制在每個帖子一個問題。
  • 如果您的代碼是功能性的,並且您想要對代碼的反饋,那么Code Review可能更適合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM