Implement Collections#sort

This is really a verbatim translation of Arrays#sort.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin 2013-10-31 00:35:40 -05:00
parent 605701e40a
commit d37b5ada37
2 changed files with 157 additions and 0 deletions

View File

@ -33,6 +33,121 @@ public class Collections {
shuffle(list, new Random());
}
public static void sort(List list) {
sort(list, new Comparator() {
public int compare(Object a, Object b) {
return ((Comparable) a).compareTo(b);
}
});
}
private final static int SORT_SIZE_THRESHOLD = 16;
public static <T> void sort(List<T> list, Comparator<? super T> comparator) {
int size = list.size();
introSort(list, comparator, 0, size, size);
insertionSort(list, comparator);
}
private static <T > void introSort(List<T> list,
Comparator<? super T> comparator, int begin, int end, int limit)
{
while (end - begin > SORT_SIZE_THRESHOLD) {
if (limit == 0) {
heapSort(list, comparator, begin, end);
return;
}
limit >>= 1;
// median of three
T a = list.get(begin);
T b = list.get(begin + (end - begin) / 2 + 1);
T c = list.get(end - 1);
T median;
if (comparator.compare(a, b) < 0) {
median = comparator.compare(b, c) < 0 ?
b : (comparator.compare(a, c) < 0 ? c : a);
} else {
median = comparator.compare(b, c) > 0 ?
b : (comparator.compare(a, c) > 0 ? c : a);
}
// partition
int pivot, i = begin, j = end;
for (;;) {
while (comparator.compare(list.get(i), median) < 0) {
++i;
}
--j;
while (comparator.compare(median, list.get(j)) < 0) {
--j;
}
if (i >= j) {
pivot = i;
break;
}
T swap = list.get(i);
list.set(i, list.get(j));
list.set(j, swap);
++i;
}
introSort(list, comparator, pivot, end, limit);
end = pivot;
}
}
private static <T> void heapSort(List<T> list, Comparator<? super T> comparator,
int begin, int end)
{
int count = end - begin;
for (int i = count / 2 - 1; i >= 0; --i) {
siftDown(list, comparator, i, count, begin);
}
for (int i = count - 1; i > 0; --i) {
// swap begin and begin + i
T swap = list.get(begin + i);
list.set(begin + i, list.get(begin));
list.set(begin, swap);
siftDown(list, comparator, 0, i, begin);
}
}
private static <T> void siftDown(List<T> list, Comparator<? super T> comparator,
int i, int count, int offset)
{
T value = list.get(offset + i);
while (i < count / 2) {
int child = 2 * i + 1;
if (child + 1 < count &&
comparator.compare(list.get(child), list.get(child + 1)) < 0) {
++child;
}
if (comparator.compare(value, list.get(child)) >= 0) {
break;
}
list.set(offset + i, list.get(offset + child));
i = child;
}
list.set(offset + i, value);
}
private static <T> void insertionSort(List<T> list,
Comparator<? super T> comparator)
{
int size = list.size();
for (int j = 1; j < size; ++j) {
T t = list.get(j);
int i = j - 1;
while (i >= 0 && comparator.compare(list.get(i), t) > 0) {
list.set(i + 1, list.get(i));
--i;
}
list.set(i + 1, t);
}
}
static <T> T[] toArray(Collection collection, T[] array) {
Class c = array.getClass().getComponentType();

View File

@ -1,9 +1,12 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class Collections {
public static void main(String[] args) {
testValues();
testSort();
}
@SuppressWarnings("rawtypes")
@ -23,4 +26,43 @@ public class Collections {
// expected
}
}
private static void expect(boolean v) {
if (! v) throw new RuntimeException();
}
private static <T extends Comparable<T>> void expectSorted(List<T> list) {
for (int i = 1; i < list.size(); ++i) {
expect(list.get(i - 1).compareTo(list.get(i)) <= 0);
}
}
private static int pseudoRandom(int seed) {
return 3170425 * seed + 132102;
}
private static <T extends Comparable<T>> int shuffle(List<T> list, int seed) {
for (int i = list.size(); i > 1; --i) {
int i2 = (seed < 0 ? -seed : seed) % i;
T value = list.get(i - 1);
list.set(i - 1, list.get(i2));
list.set(i2, value);
seed = pseudoRandom(seed);
}
return seed;
}
public static void testSort() {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 64; ++i) {
list.add(Integer.valueOf(i + 1));
}
;
int random = 12345;
for (int i = 0; i < 32; ++i) {
random = shuffle(list, random);
java.util.Collections.sort(list);
expectSorted(list);
}
}
}