[英]A generic MergeSort implementation in java
我編寫了一個 MergeSort 實現,它應該對任何數據類型的數組進行排序。
我在這里面臨兩個問題。
由於泛型類型不能定義為數組,因為編譯器錯誤說“無法創建 T 的泛型數組”,因此我遵循了 StackOverflow 中的一個線程中建議的 kludge 使用
T[] right = (T[]) Array.newInstance(clazz, rightSize);
因此,使用運行時提供的類型信息,我們仍然可以實例化一個數組並將其轉換回 T[],盡管無論我們是否處理它,它仍然容易受到 ClassCastException 的影響。
有沒有其他有效和理想的方法來實現這一目標?
那么我是否需要為我想要排序的每個原始類型數組創建一個版本的 MergeSort 類?
任何幫助將不勝感激。 謝謝。
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[]
。
對於您的第三個問題:您可以重新使用舊數組,而不是為左右部分創建新數組,而只需將left
和right
作為參數傳遞left
您的遞歸調用。 有關實現,請參閱此 github 鏈接。
代碼注釋:在 Java 中,方法名稱應始終以小寫字母開頭。 雖然我知道在 C++ 中用_
啟動私有方法是很常見的,但在 Java 中情況並非如此。
對你的問題的一些一般性評論:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.