tdlight-java/tdlight-java/src/main/java/it/tdlight/ArrayUtil.java

125 lines
2.5 KiB
Java

package it.tdlight;
import it.tdlight.util.IntSwapper;
class ArrayUtil {
public interface IntComparator {
int compare(int k1, int k2);
}
public static void mergeSort(int from, int to, IntComparator c, IntSwapper swapper) {
int length = to - from;
int i;
if (length >= 16) {
i = from + to >>> 1;
mergeSort(from, i, c, swapper);
mergeSort(i, to, c, swapper);
if (c.compare(i - 1, i) > 0) {
inPlaceMerge(from, i, to, c, swapper);
}
} else {
for(i = from; i < to; ++i) {
for(int j = i; j > from && c.compare(j - 1, j) > 0; --j) {
swapper.swap(j, j - 1);
}
}
}
}
private static void inPlaceMerge(int from, int mid, int to, IntComparator comp, IntSwapper swapper) {
if (from < mid && mid < to) {
if (to - from == 2) {
if (comp.compare(mid, from) < 0) {
swapper.swap(from, mid);
}
} else {
int firstCut;
int secondCut;
if (mid - from > to - mid) {
firstCut = from + (mid - from) / 2;
secondCut = lowerBound(mid, to, firstCut, comp);
} else {
secondCut = mid + (to - mid) / 2;
firstCut = upperBound(from, mid, secondCut, comp);
}
if (mid != firstCut && mid != secondCut) {
int first1 = firstCut;
int last1 = mid;
label43:
while(true) {
--last1;
if (first1 >= last1) {
first1 = mid;
last1 = secondCut;
while(true) {
--last1;
if (first1 >= last1) {
first1 = firstCut;
last1 = secondCut;
while(true) {
--last1;
if (first1 >= last1) {
break label43;
}
swapper.swap(first1++, last1);
}
}
swapper.swap(first1++, last1);
}
}
swapper.swap(first1++, last1);
}
}
mid = firstCut + (secondCut - mid);
inPlaceMerge(from, firstCut, mid, comp, swapper);
inPlaceMerge(mid, secondCut, to, comp, swapper);
}
}
}
private static int lowerBound(int from, int to, int pos, IntComparator comp) {
int len = to - from;
while(len > 0) {
int half = len / 2;
int middle = from + half;
if (comp.compare(middle, pos) < 0) {
from = middle + 1;
len -= half + 1;
} else {
len = half;
}
}
return from;
}
private static int upperBound(int from, int mid, int pos, IntComparator comp) {
int len = mid - from;
while(len > 0) {
int half = len / 2;
int middle = from + half;
if (comp.compare(pos, middle) < 0) {
len = half;
} else {
from = middle + 1;
len -= half + 1;
}
}
return from;
}
}