Merge "IntList: add #sort using quick sort for O(n log n) runtime."
This commit is contained in:
commit
f9f3389847
|
@ -15,6 +15,7 @@
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.eclipse.jgit.util.IntList.IntComparator;
|
||||
import org.junit.Test;
|
||||
|
||||
public class IntListTest {
|
||||
|
@ -42,6 +43,15 @@ public void testEmpty_SpecificCapacity() {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilledWithRange() {
|
||||
IntList list = IntList.filledWithRange(-2, 13);
|
||||
assertEquals(15, list.size());
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
assertEquals(i - 2, list.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd_SmallGroup() {
|
||||
final IntList i = new IntList();
|
||||
|
@ -163,6 +173,22 @@ public void testContains() {
|
|||
assertFalse(i.contains(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSort_byAbs() {
|
||||
IntList list = new IntList();
|
||||
list.add(-3);
|
||||
list.add(-2);
|
||||
list.add(0);
|
||||
list.add(1);
|
||||
list.add(4);
|
||||
list.add(1);
|
||||
list.sort(new AbsIntComparator());
|
||||
int[] expected = { 0, 1, 1, -2, -3, 4 };
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
assertEquals(expected[i], list.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
final IntList i = new IntList();
|
||||
|
@ -173,4 +199,12 @@ public void testToString() {
|
|||
assertEquals("[1, 13, 5]", i.toString());
|
||||
}
|
||||
|
||||
private static class AbsIntComparator implements IntComparator {
|
||||
private AbsIntComparator() {
|
||||
}
|
||||
|
||||
public int compare(int a, int b) {
|
||||
return Math.abs(a) - Math.abs(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,24 @@ public IntList(int capacity) {
|
|||
entries = new int[capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list initialized with the values of the given range.
|
||||
*
|
||||
* @param start
|
||||
* the beginning of the range, inclusive
|
||||
* @param end
|
||||
* the end of the range, exclusive
|
||||
* @return the list initialized with the given range
|
||||
* @since 6.6
|
||||
*/
|
||||
public static IntList filledWithRange(int start, int end) {
|
||||
IntList list = new IntList(end - start);
|
||||
for (int val = start; val < end; val++) {
|
||||
list.add(val);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of entries in this list.
|
||||
*
|
||||
|
@ -126,6 +144,60 @@ public void fillTo(int toIndex, int val) {
|
|||
add(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the entries of the list in-place, according to the comparator.
|
||||
*
|
||||
* @param comparator
|
||||
* provides the comparison values for sorting the entries
|
||||
* @since 6.6
|
||||
*/
|
||||
public void sort(IntComparator comparator) {
|
||||
quickSort(0, count - 1, comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick sort has average time complexity of O(n log n) and O(log n) space
|
||||
* complexity (for recursion on the stack).
|
||||
* <p>
|
||||
* Implementation based on https://www.baeldung.com/java-quicksort.
|
||||
*
|
||||
* @param begin
|
||||
* the index to begin partitioning at, inclusive
|
||||
* @param end
|
||||
* the index to end partitioning at, inclusive
|
||||
* @param comparator
|
||||
* provides the comparison values for sorting the entries
|
||||
*/
|
||||
private void quickSort(int begin, int end, IntComparator comparator) {
|
||||
if (begin < end) {
|
||||
int partitionIndex = partition(begin, end, comparator);
|
||||
|
||||
quickSort(begin, partitionIndex - 1, comparator);
|
||||
quickSort(partitionIndex + 1, end, comparator);
|
||||
}
|
||||
}
|
||||
|
||||
private int partition(int begin, int end, IntComparator comparator) {
|
||||
int pivot = entries[end];
|
||||
int writeSmallerIdx = (begin - 1);
|
||||
|
||||
for (int findSmallerIdx = begin; findSmallerIdx < end; findSmallerIdx++) {
|
||||
if (comparator.compare(entries[findSmallerIdx], pivot) <= 0) {
|
||||
writeSmallerIdx++;
|
||||
|
||||
int biggerVal = entries[writeSmallerIdx];
|
||||
entries[writeSmallerIdx] = entries[findSmallerIdx];
|
||||
entries[findSmallerIdx] = biggerVal;
|
||||
}
|
||||
}
|
||||
|
||||
int pivotIdx = writeSmallerIdx + 1;
|
||||
entries[end] = entries[pivotIdx];
|
||||
entries[pivotIdx] = pivot;
|
||||
|
||||
return pivotIdx;
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
final int[] n = new int[(entries.length + 16) * 3 / 2];
|
||||
System.arraycopy(entries, 0, n, 0, count);
|
||||
|
@ -145,4 +217,22 @@ public String toString() {
|
|||
r.append(']');
|
||||
return r.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparator of primitive ints.
|
||||
*/
|
||||
public interface IntComparator {
|
||||
|
||||
/**
|
||||
* Compares the two int arguments for order.
|
||||
*
|
||||
* @param first
|
||||
* the first int to compare
|
||||
* @param second
|
||||
* the second int to compare
|
||||
* @return a negative number if first < second, 0 if first == second, or
|
||||
* a positive number if first > second
|
||||
*/
|
||||
int compare(int first, int second);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue