private <T extends Comparable<T>> void sort(T[] array, int lo, int hi, boolean ascend) {
// OPTIMIZE ONE
// if the substring's length is less than 20,
// use insertion sort to reduce recursive invocation
if (hi - lo < 20) {
for (int i = lo + 1; i <= hi; i++) {
T toInsert = array;
int j = i;
for (; j > lo; j--) {
int compare = array[j - 1].compareTo(toInsert);
if (compare == 0 || compare < 0 == ascend) {
break;
}
array[j] = array[j - 1];
}
private <T extends Comparable<T>> void merge(T[] array, int lo, int mid, int hi, boolean ascend) {
// OPTIMIZE TWO
// if it is already in right order, skip this merge
// since there's no need to do so
int leftEndCompareToRigthStart = array[mid].compareTo(array[mid + 1]);
if (leftEndCompareToRigthStart == 0 || leftEndCompareToRigthStart < 0 == ascend) {
return;
}
@SuppressWarnings("unchecked")
T[] arrayCopy = (T[]) new Comparable[hi - lo + 1];
System.arraycopy(array, lo, arrayCopy, 0, arrayCopy.length);
int lowIdx = 0;
int highIdx = mid - lo + 1;
for (int i = lo; i <= hi; i++) {
if (lowIdx > mid - lo) {
// left sub array exhausted
array = arrayCopy[highIdx++];
} else if (highIdx > hi - lo) {
// right sub array exhausted
array = arrayCopy[lowIdx++];
} else if (arrayCopy[lowIdx].compareTo(arrayCopy[highIdx]) < 0 == ascend) {
array = arrayCopy[lowIdx++];
} else {
array = arrayCopy[highIdx++];
}
}
}
})
private <T extends Comparable<T>> void sort(T[] array, int lo, int hi, boolean ascend) {
if (lo >= hi) {
return;
}
T toFinal = array[lo];
int leftIdx = lo;
int rightIdx = hi;
int i = lo + 1;
while (i <= rightIdx) {
int compare = array.compareTo(toFinal);
if (compare == 0) {
i++;
} else if (compare < 0 == ascend) {
exchange(array, leftIdx++, i++);
} else {
exchange(array, rightIdx--, i);
}
}
// partially sort left array and right array
// no need to include the leftIdx-th to rightIdx-th elements
// since they are already in its final position
sort(array, lo, leftIdx - 1, ascend);
sort(array, rightIdx + 1, hi, ascend);
}
})