[Home] DMelt member access . Java source code: cc.redberry.core.utils.ArraysUtils
/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2015:
* Stanislav Poslavsky
* Bolotin Dmitriy
*
* This file is part of Redberry.
*
* Redberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Redberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Redberry. If not, see .
*/
package cc.redberry.core.utils;
import cc.redberry.core.tensor.Tensor;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Set;
/**
* This class contains additional methods for manipulating arrays (such as sorting and searching). For all quick sort
* methods the base code was taken from jdk6 {@link Arrays} class.
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
* @see Arrays
*/
public final class ArraysUtils {
public static final Comparator HASH_COMPARATOR = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return Integer.compare(o1.hashCode(), o2.hashCode());
}
};
private ArraysUtils() {
}
public static void arraycopy(IntArray source, int srcPos, int[] dest, int destPos, int length) {
System.arraycopy(source.innerArray, srcPos, dest, destPos, length);
}
public static int[] short2int(final short[] a) {
int[] r = new int[a.length];
for (int i = 0; i < a.length; ++i)
r[i] = a[i];
return r;
}
public static short[] int2short(final int[] a) {
short[] r = new short[a.length];
for (int i = 0; i < a.length; ++i)
r[i] = (short) a[i];
return r;
}
public static int[] byte2int(final byte[] a) {
int[] r = new int[a.length];
for (int i = 0; i < a.length; ++i)
r[i] = a[i];
return r;
}
public static short[] byte2short(final byte[] a) {
short[] r = new short[a.length];
for (int i = 0; i < a.length; ++i)
r[i] = a[i];
return r;
}
public static byte[] int2byte(final int[] a) {
byte[] r = new byte[a.length];
for (int i = 0; i < a.length; ++i)
r[i] = (byte) a[i];
return r;
}
public static int max(int[] array) {
int a = -1;
for (int i : array)
a = Math.max(a, i);
return a;
}
public static int[] getSeriesFrom0(int size) {
int[] ret = new int[size];
for (int i = size; i >= 0; ++i)
ret[i] = i;
return ret;
}
public static int[][] deepClone(int[][] input) {
int[][] res = new int[input.length][];
for (int i = res.length - 1; i >= 0; --i)
res[i] = input[i].clone();
return res;
}
public static int sum(final int[] array) {
int s = 0;
for (int i : array)
s += i;
return s;
}
/**
* This method is similar to {@link #bijection(Comparable[], Comparable[])} }, but uses specified {@code
* comparator}.
*
* @param from from array
* @param to to array
* @param comparator comparator
* @return a bijective mapping from {@code from}-array to {@code to}-array and {@code null} if no mapping exist
*/
public static int[] bijection(T[] from, T[] to, Comparator super T> comparator) {
//TODO refactor with sorting !!!!
if (from.length != to.length)
return null;
int length = from.length;
int[] bijection = new int[length];
Arrays.fill(bijection, -1);
int i, j;
OUT:
for (i = 0; i < length; ++i) {
for (j = 0; j < length; ++j)
if (bijection[j] == -1 && comparator.compare(from[i], to[j]) == 0) {
bijection[j] = i;
continue OUT;
}
return null;
}
return bijection;
}
/**
* Creates a bijective mapping between two arrays and returns the resulting bijection as array. Method returns null,
* if no mapping found.
* Example:
* Integer from[] = {1,2,1,4};
* Integer to[] = {2,4,1,1};
* int[] bijection = bijection(from,to);
*
*
The resulting bijection will be {@code [2, 0, 3, 1]}
*
* @param from from array
* @param to to array
* @return a bijective mapping from {@code from}-array to {@code to}-array and {@code null} if no mapping exist
*/
public static > int[] bijection(T[] from, T[] to) {
//TODO refactor with sorting !!!!
if (from.length != to.length)
return null;
int length = from.length;
int[] bijection = new int[length];
Arrays.fill(bijection, -1);
int i, j;
OUT:
for (i = 0; i < length; ++i) {
for (j = 0; j < length; ++j)
if (bijection[j] == -1 && from[i].compareTo(to[j]) == 0) {
bijection[j] = i;
continue OUT;
}
return null;
}
return bijection;
}
public static Tensor[] addAll(Tensor[] array1, Tensor... array2) {
Tensor[] r = new Tensor[array1.length + array2.length];
System.arraycopy(array1, 0, r, 0, array1.length);
System.arraycopy(array2, 0, r, array1.length, array2.length);
return r;
}
public static int[] addAll(int[] array1, int... array2) {
int[] r = new int[array1.length + array2.length];
System.arraycopy(array1, 0, r, 0, array1.length);
System.arraycopy(array2, 0, r, array1.length, array2.length);
return r;
}
public static int[] addAll(int[]... arrays) {
if (arrays.length == 0)
return new int[0];
int i, length = 0;
for (i = 0; i < arrays.length; ++i)
length += arrays[i].length;
if (length == 0)
return new int[0];
int[] r = new int[length];
int pointer = 0;
for (i = 0; i < arrays.length; ++i) {
System.arraycopy(arrays[i], 0, r, pointer, arrays[i].length);
pointer += arrays[i].length;
}
return r;
}
public static Tensor[] remove(Tensor[] array, int i) {
Tensor[] r = new Tensor[array.length - 1];
System.arraycopy(array, 0, r, 0, i);
if (i < array.length - 1)
System.arraycopy(array, i + 1, r, i, array.length - i - 1);
return r;
}
public static T[] remove(T[] array, int i) {
@SuppressWarnings("unchecked")
T[] r = (T[]) Array.newInstance(array.getClass().getComponentType(), array.length - 1);
System.arraycopy(array, 0, r, 0, i);
if (i < array.length - 1)
System.arraycopy(array, i + 1, r, i, array.length - i - 1);
return r;
}
/**
* This code is taken from Apache Commons Lang ArrayUtils.
Adds all the elements of the given arrays into a
* new array.
The new array contains all of the element of {@code array1} followed by all of the elements
* {@code array2}. When an array is returned, it is always a new array.
*
* ArrayUtils.addAll(null, null) = null
* ArrayUtils.addAll(array1, null) = cloned copy of array1
* ArrayUtils.addAll(null, array2) = cloned copy of array2
* ArrayUtils.addAll([], []) = []
* ArrayUtils.addAll([null], [null]) = [null, null]
* ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
*
*
* @param the component type of the array
* @param array1 the first array whose elements are added to the new array, may be {@code null}
* @param array2 the second array whose elements are added to the new array, may be {@code null}
* @return The new array, {@code null} if both arrays are {@code null}. The type of the new array is the type of the
* first array, unless the first array is null, in which case the type is the same as the second array.
* @throws IllegalArgumentException if the array types are incompatible
* @since 2.1
*/
@SafeVarargs
public static T[] addAll(T[] array1, T... array2) {
if (array1 == null)
return array2.clone();
else if (array2 == null)
return array1.clone();
final Class> type1 = array1.getClass().getComponentType();
@SuppressWarnings("unchecked") // OK, because array is of type T
T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
System.arraycopy(array1, 0, joinedArray, 0, array1.length);
try {
System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
} catch (ArrayStoreException ase) {
// Check if problem was due to incompatible types
/*
* We do this here, rather than before the copy because: - it would
* be a wasted check most of the time - safer, in case check turns
* out to be too strict
*/
final Class> type2 = array2.getClass().getComponentType();
if (!type1.isAssignableFrom(type2))
throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
+ type1.getName(), ase);
throw ase; // No, so rethrow original
}
return joinedArray;
}
/**
* Removes elements at specified {@code positions} in specified {@code array}. This method preserve
* the relative order of elements in specified {@code array}.
*
* @param array array of elements
* @param positions positions of elements that should be removed
* @param generic type
* @return new array with removed elements at specified positions
* @throws ArrayIndexOutOfBoundsException if some position larger then array length
*/
public static T[] remove(T[] array, int[] positions) {
if (array == null)
throw new NullPointerException();
int[] p = MathUtils.getSortedDistinct(positions);
if (p.length == 0)
return array;
int size = p.length, pointer = 0, s = array.length;
for (; pointer < size; ++pointer)
if (p[pointer] >= s)
throw new ArrayIndexOutOfBoundsException();
final Class> type = array.getClass().getComponentType();
@SuppressWarnings("unchecked") // OK, because array is of type T
T[] r = (T[]) Array.newInstance(type, array.length - p.length);
pointer = 0;
int i = -1;
for (int j = 0; j < s; ++j) {
if (pointer < size - 1 && j > p[pointer])
++pointer;
if (j == p[pointer]) continue;
else r[++i] = array[j];
}
return r;
}
//for performance
/**
* Removes elements at specified {@code positions} in specified {@code array}. This method preserve
* the relative order of elements in specified {@code array}.
*
* @param array array of elements
* @param positions positions of elements that should be removed
* @return new array with removed elements at specified positions
* @throws ArrayIndexOutOfBoundsException if some position larger then array length
*/
public static Tensor[] remove(Tensor[] array, int[] positions) {
if (array == null)
throw new NullPointerException();
int[] p = MathUtils.getSortedDistinct(positions);
if (p.length == 0)
return array;
int size = p.length, pointer = 0, s = array.length;
for (; pointer < size; ++pointer)
if (p[pointer] >= s)
throw new ArrayIndexOutOfBoundsException();
final Class> type = array.getClass().getComponentType();
Tensor[] r = new Tensor[array.length - p.length];
pointer = 0;
int i = -1;
for (int j = 0; j < s; ++j) {
if (pointer < size - 1 && j > p[pointer])
++pointer;
if (j == p[pointer]) continue;
else r[++i] = array[j];
}
return r;
}
/**
* Removes elements at specified {@code positions} in specified {@code array}. This method preserve
* the relative order of elements in specified {@code array}.
*
* @param array array of elements
* @param positions positions of elements that should be removed
* @return new array with removed elements at specified positions
* @throws ArrayIndexOutOfBoundsException if some position larger then array length
*/
public static int[] remove(int[] array, int[] positions) {
if (array == null)
throw new NullPointerException();
int[] p = MathUtils.getSortedDistinct(positions.clone());
if (p.length == 0)
return array;
int size = p.length, pointer = 0, s = array.length;
for (; pointer < size; ++pointer)
if (p[pointer] >= s)
throw new ArrayIndexOutOfBoundsException();
int[] r = new int[array.length - p.length];
pointer = 0;
int i = -1;
for (int j = 0; j < s; ++j) {
if (pointer < size - 1 && j > p[pointer])
++pointer;
if (j == p[pointer]) continue;
else r[++i] = array[j];
}
return r;
}
/**
* Selects elements from specified {@code array} at specified {@code positions}. The resulting array preserves
* the relative order of elements in specified {@code array}.
*
* @param array array of elements
* @param positions of elements that should be picked out
* @param generic type
* @return the array of elements that picked out from specified positions in specified array
*/
public static T[] select(T[] array, int[] positions) {
if (array == null)
throw new NullPointerException();
int[] p = MathUtils.getSortedDistinct(positions);
final Class> type = array.getClass().getComponentType();
@SuppressWarnings("unchecked") // OK, because array is of type T
T[] r = (T[]) Array.newInstance(type, p.length);
int i = -1;
for (int j : p)
r[++i] = array[j];
return r;
}
/**
* Converts {@code Set} to {@code int[]}
*
* @param set a {@link Set} of {@link Integer}
* @return {@code int[]}
*/
public static int[] toArray(Set set) {
int i = -1;
int[] a = new int[set.size()];
for (Integer ii : set)
a[++i] = ii;
return a;
}
/**
* Assigns the specified int value to each element of the specified
* range of the specified list. The range to be filled
* extends from index fromIndex , inclusive, to index
* toIndex , exclusive. (If fromIndex==toIndex , the
* range to be filled is empty.)
*
* @param list the list to be filled
* @param fromIndex the index of the first element (inclusive) to be
* filled with the specified value
* @param toIndex the index of the last element (exclusive) to be
* filled with the specified value
* @param value the value to be stored in all elements of the array
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or
* toIndex > a.length
*/
public static void fill(IntArrayList list, int fromIndex, int toIndex, int value) {
if (toIndex >= list.size())
throw new IndexOutOfBoundsException();
Arrays.fill(list.data, fromIndex, toIndex, value);
}
/**
* Assigns the specified int value to each element of the specified list
* of ints.
*
* @param list the array to be filled
* @param value the value to be stored in all elements of the array
*/
public static void fill(IntArrayList list, int value) {
fill(list, 0, list.size(), value);
}
/**
* Searches a range of
* the specified array of ints for the specified value using the
* binary search algorithm.
* The range must be sorted (as
* by the {@link cc.redberry.core.utils.IntArrayList#sort()} method)
* prior to making this call. If it
* is not sorted, the results are undefined. If the range contains
* multiple elements with the specified value, there is no guarantee which
* one will be found.
*
* @param list the list to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array
* within the specified range;
* otherwise, (-(insertion point ) - 1) . The
* insertion point is defined as the point at which the
* key would be inserted into the array: the index of the first
* element in the range greater than the key,
* or toIndex if all
* elements in the range are less than the specified key. Note
* that this guarantees that the return value will be >= 0 if
* and only if the key is found.
* @see Arrays#binarySearch(int[], int)
*/
public static int binarySearch(IntArrayList list, int key) {
return Arrays.binarySearch(list.data, 0, list.size, key);
}
/**
* Searches a range of
* the specified array of ints for the specified value using the
* binary search algorithm.
* The range must be sorted (as
* by the {@link cc.redberry.core.utils.IntArrayList#sort()} method)
* prior to making this call. If it
* is not sorted, the results are undefined. If the range contains
* multiple elements with the specified value, there is no guarantee which
* one will be found.
*
* @param array the list to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array
* within the specified range;
* otherwise, (-(insertion point ) - 1) . The
* insertion point is defined as the point at which the
* key would be inserted into the array: the index of the first
* element in the range greater than the key,
* or toIndex if all
* elements in the range are less than the specified key. Note
* that this guarantees that the return value will be >= 0 if
* and only if the key is found.
* @see Arrays#binarySearch(int[], int)
*/
public static int binarySearch(IntArray array, int key) {
return Arrays.binarySearch(array.innerArray, 0, array.innerArray.length, key);
}
/**
* This is the same method to {@link Arrays#binarySearch(int[], int) }. The differs is in the returned value. If key
* not found, this method returns the position of the first element, witch is closest to key (i.e. if
* Arrays.binarySearch returns {@code -low-1}, this method returns {@code low}).
*
* @param a the array to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array; otherwise, insertion point . The
* insertion point is defined as the point at which the key would be inserted into the array: the
* index of the first element greater than the key, or a.length if all elements in the array are
* less than the specified key.
*/
public static int binarySearch1(int[] a, int key) {
return binarySearch1(a, 0, a.length, key);
}
/**
* This is the same method to {@link Arrays#binarySearch(int[], int, int, int) }. The differs is in the returned
* value. If key not found, this method returns the position of the first element, witch is closest to key (i.e. if
* Arrays.binarySearch returns {@code -low-1}, this method returns {@code low}).
*
* @param a the array to be searched
* @param key the value to be searched for
* @param fromIndex the index of the first element (inclusive) to be searched
* @param toIndex the index of the last element (exclusive) to be searched
* @return index of the search key, if it is contained in the array; otherwise, insertion point . The
* insertion point is defined as the point at which the key would be inserted into the array: the
* index of the first element greater than the key, or toIndex if all elements in the array are
* less than the specified key.
*/
public static int binarySearch1(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else {
while (mid > 0 && a[mid - 1] == a[mid]) --mid;
return mid; // key found
}
}
if (low >= a.length) return low;
while (low > 0 && a[low - 1] == a[low]) --low;
return low; // key not found.
}
/**
* Returns xor of objects hashes via {@link HashFunctions#JenkinWang32shift(int) }
*
* @param objects array
* @return commutative hash
*/
public static int commutativeHashCode(final Object[] objects) {
if (objects == null)
return 0;
int hash = 0;
for (Object o : objects)
hash ^= (o == null ? 0 : o.hashCode());
return HashFunctions.JenkinWang32shift(hash);
}
/**
* Returns xor of objects hashes spreaded by {@link HashFunctions#JenkinWang32shift(int) }
*
* @param objects array
* @return commutative hash
*/
public static int commutativeHashCode(final Object[] objects, final int from, final int to) {
rangeCheck(objects.length, from, to);
if (objects == null)
return 0;
int hash = 0;
for (int i = from; i < to; ++i)
hash ^= (objects[i] == null ? 0 : objects[i].hashCode());
return HashFunctions.JenkinWang32shift(hash);
}
/**
* Sorts the specified array of ints into ascending order using insertion sort algorithm and simultaneously permutes
* the {@code coSort} ints array in the same way as the target array. This sort guarantee O(n^2) performance
* in the worst case and O(n) in the best case (nearly sorted input).
This sort is the best choice for
* small arrays with elements number < 100.
This sort is guaranteed to be stable : equal elements will
* not be reordered as a result of the sort; adaptive : performance adapts to the initial order of elements
* and in-place : requires constant amount of additional space.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static void insertionSort(int[] target, int[] coSort) {
insertionSort(target, 0, target.length, coSort);
}
/**
* Sorts the specified array of ints into ascending order using insertion sort algorithm and simultaneously permutes
* the {@code coSort} ints array in the same way as the target array. This sort guarantee O(n^2) performance
* in the worst case and O(n) in the best case (nearly sorted input). The range to be sorted extends from index
* fromIndex , inclusive, to index toIndex , exclusive. (If fromIndex==toIndex , the range
* to be sorted is empty.)
This sort is the best choice for small arrays with elements number < 100.
* This sort is guaranteed to be stable : equal elements will not be reordered as a result of the sort;
* adaptive : performance adapts to the initial order of elements and in-place : requires constant
* amount of additional space.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static void insertionSort(int[] target, int fromIndex, int toIndex, int[] coSort) {
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
int i, key, j, keyC;
for (i = fromIndex + 1; i < toIndex; i++) {
key = target[i];
keyC = coSort[i];
for (j = i; j > fromIndex && target[j - 1] > key; j--) {
target[j] = target[j - 1];
coSort[j] = coSort[j - 1];
}
target[j] = key;
coSort[j] = keyC;
}
}
/**
* Sorts the specified array of ints into ascending order using insertion sort algorithm and simultaneously permutes
* the {@code coSort} longs array in the same way as the specified target array. This sort guarantee O(n^2)
* performance in the worst case and O(n) in the best case (nearly sorted input).
This sort is the best
* choice for small arrays with elements number < 100.
This sort is guaranteed to be stable : equal
* elements will not be reordered as a result of the sort; adaptive : performance adapts to the initial order
* of elements and in-place : requires constant amount of additional space.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static void insertionSort(int[] target, long[] coSort) {
insertionSort(target, 0, target.length, coSort);
}
/**
* Sorts the specified array of ints into ascending order using insertion sort algorithm and simultaneously permutes
* the {@code coSort} ints array in the same way as the target array. This sort guarantee O(n^2) performance
* in the worst case and O(n) in the best case (nearly sorted input). The range to be sorted extends from index
* fromIndex , inclusive, to index toIndex , exclusive. (If fromIndex==toIndex , the range
* to be sorted is empty.)
This sort is the best choice for small arrays with elements number < 100.
* This sort is guaranteed to be stable : equal elements will not be reordered as a result of the sort;
* adaptive : performance adapts to the initial order of elements and in-place : requires constant
* amount of additional space.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the specified target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static void insertionSort(int[] target, int fromIndex, int toIndex, long[] coSort) {
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
int i, key, j;
long keyC;
for (i = fromIndex + 1; i < toIndex; i++) {
key = target[i];
keyC = coSort[i];
for (j = i; j > fromIndex && target[j - 1] > key; j--) {
target[j] = target[j - 1];
coSort[j] = coSort[j - 1];
}
target[j] = key;
coSort[j] = keyC;
}
}
/**
* Sorts the specified target array of objects into ascending order, according to the natural ordering of its
* elements using insertion sort algorithm and simultaneously permutes the {@code coSort} objects array in the same
* way then specified target array. This sort guarantee O(n^2) performance in the worst case and O(n) in the best
* case (nearly sorted input).
This sort is the best choice for small arrays with elements number < 100.
*
This sort is guaranteed to be stable : equal elements will not be reordered as a result of the
* sort; adaptive : performance adapts to the initial order of elements and in-place : requires constant
* amount of additional space.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static > void insertionSort(T[] target, Object[] coSort) {
insertionSort(target, 0, target.length, coSort);
}
/**
* Sorts the specified target array of objects into ascending order, according to the natural ordering of its
* elements using insertion sort algorithm and simultaneously permutes the {@code coSort} objects array in the same
* way then specified target array. This sort guarantee O(n^2) performance in the worst case and O(n) in the best
* case (nearly sorted input). The range to be sorted extends from index fromIndex , inclusive, to index
* toIndex , exclusive. (If fromIndex==toIndex , the range to be sorted is empty.)
This
* sort is the best choice for small arrays with elements number < 100.
This sort is guaranteed to be
* stable : equal elements will not be reordered as a result of the sort; adaptive : performance adapts
* to the initial order of elements and in-place : requires constant amount of additional space.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static > void insertionSort(T[] target, int fromIndex, int toIndex, Object[] coSort) {
int i, j;
T key;
Object keyC;
for (i = fromIndex + 1; i < toIndex; i++) {
key = target[i];
keyC = coSort[i];
for (j = i; j > fromIndex && target[j - 1].compareTo(key) > 0; j--) {
target[j] = target[j - 1];
coSort[j] = coSort[j - 1];
}
target[j] = key;
coSort[j] = keyC;
}
}
/**
* Sorts the specified array of ints into ascending order using TimSort algorithm and simultaneously permutes the
* {@code coSort} ints array in the same way as the target array.
NOTE: using of this method is
* very good for large arrays with more then 100 elements, in other case using of insertion sort is highly
* recommended.
This sort is guaranteed to be stable : equal elements will not be reordered as a
* result of the sort.
The code was taken from {@link Arrays#sort(java.lang.Object[]) } and adapted for
* integers. For more information look there.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws ClassCastException if the array contains elements that are not mutually comparable (for example,
* strings and integers)
* @see Arrays#sort(java.lang.Object[])
*/
public static void timSort(int target[], int[] coSort) {
IntTimSort.sort(target, coSort);
}
/**
* Sorts the specified array of ints into ascending order using stable sort algorithm and simultaneously permutes
* the {@code coSort} ints array in the same way as the target array. If length of specified array is less
* than 100 - insertion sort algorithm performed, otherwise - TimSort.
This sort is guaranteed to be
* stable : equal elements will not be reordered as a result of the sort.
*
* @param target the array to be sorted
* @param cosort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws ClassCastException if the array contains elements that are not mutually comparable (for
* example, strings and integers)
* @throws IllegalArgumentException if coSort length less then target length.
* @throws IllegalArgumentException if target == coSort (as references).
* @see #insertionSort(int[], int[])
* @see #timSort(int[], int[])
*/
public static void stableSort(int target[], int[] cosort) {
if (target.length > 100)
ArraysUtils.timSort(target, cosort);
else
ArraysUtils.insertionSort(target, cosort);
}
/**
* Sorts the specified array and returns the resulting permutation
*
* @param target int array
* @return sorting permutation
*/
public static int[] quickSortP(int[] target) {
int[] permutation = new int[target.length];
for (int i = 1; i < target.length; ++i)
permutation[i] = i;
quickSort(target, 0, target.length, permutation);
return permutation;
}
/**
* Sorts the specified target array of ints into ascending numerical order and simultaneously permutes the {@code
* coSort} ints array in the same way as the target array.
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: remember this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
NOTE: The method throws {@code
* IllegalArgumentException} if {@code target == coSort}, because in this case no sorting will be perfomed.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if coSort length less then target length.
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static void quickSort(int[] target, int[] coSort) {
quickSort(target, 0, target.length, coSort);
}
/**
* Sorts the specified range of the specified target array of ints into ascending numerical order and simultaneously
* permutes the {@code coSort} ints array in the same way as the target array. The range to be sorted
* extends from index fromIndex , inclusive, to index toIndex , exclusive. (If
* fromIndex==toIndex , the range to be sorted is empty.)
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: remember this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
NOTE: The method throws {@code
* IllegalArgumentException} if {@code target == coSort}, because in this case no sorting will be perfomed.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static void quickSort(int[] target, int fromIndex, int toIndex, int[] coSort) {
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
quickSort1(target, fromIndex, toIndex - fromIndex, coSort);
}
/**
* This method is the same as {@link #quickSort(int[], int, int, int[]) }, but without range checking and toIndex ->
* length (see params). Throws {@code IllegalArgumentException} if {@code target == coSort}, because in this case no
* sorting will be perfomed .
NOTE: this is unstable sort algorithm, so additional combinatorics of the
* {@code coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use
* stable sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static void quickSort1(int target[], int fromIndex, int length, int[] coSort) {
if (target == coSort)
throw new IllegalArgumentException("Target reference == coSort reference.");
quickSort2(target, fromIndex, length, coSort);
}
private static void quickSort2(int target[], int fromIndex, int length, int[] coSort) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && target[j - 1] > target[j]; j--)
swap(target, j, j - 1, coSort);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s);
m = med3(target, m - s, m, m + s);
n = med3(target, n - 2 * s, n - s, n);
}
m = med3(target, l, m, n); // Mid-size, med of 3
}
int v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && target[b] <= v) {
if (target[b] == v)
swap(target, a++, b, coSort);
b++;
}
while (c >= b && target[c] >= v) {
if (target[c] == v)
swap(target, c, d--, coSort);
c--;
}
if (b > c)
break;
swap(target, b++, c--, coSort);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s, coSort);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s, coSort);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort2(target, fromIndex, s, coSort);
if ((s = d - c) > 1)
quickSort2(target, n - s, s, coSort);
}
private static void swap(int x[], int a, int b, int[] coSort) {
swap(x, a, b);
swap(coSort, a, b);
}
/**
* Swaps x[a] with x[b].
*/
public static void swap(int x[], int a, int b) {
int t = x[a];
x[a] = x[b];
x[b] = t;
}
private static void vecswap(int x[], int a, int b, int n, int[] coSort) {
for (int i = 0; i < n; i++, a++, b++)
swap(x, a, b, coSort);
}
/**
* Returns the index of the median of the three indexed integers.
*/
private static int med3(int x[], int a, int b, int c) {
return (x[a] < x[b]
? (x[b] < x[c] ? b : x[a] < x[c] ? c : a)
: (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
}
/**
* Sorts the specified target array of ints into ascending numerical order and simultaneously permutes the {@code
* coSort} longs array in the same way as the target array.
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static void quickSort(int[] target, long[] coSort) {
quickSort1(target, 0, target.length, coSort);
}
/**
* Sorts the specified range of the specified target array of ints into ascending numerical order and simultaneously
* permutes the {@code coSort} longs array in the same way as the target array. The range to be sorted
* extends from index fromIndex , inclusive, to index toIndex , exclusive. (If
* fromIndex==toIndex , the range to be sorted is empty.)
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be performed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static void quickSort(int[] target, int fromIndex, int toIndex, long[] coSort) {
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
quickSort1(target, fromIndex, toIndex - fromIndex, coSort);
}
/**
* This method is the same as {@link #quickSort(int[], int, int, long[]) ) }, but without range checking.
* NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code coSort} array can be
* performed. Use this method only if you are sure, in what you are doing. If not - use stable sort methods like an
* insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
*/
public static void quickSort1(int target[], int fromIndex, int length, long[] coSort) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && target[j - 1] > target[j]; j--)
swap(target, j, j - 1, coSort);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s);
m = med3(target, m - s, m, m + s);
n = med3(target, n - 2 * s, n - s, n);
}
m = med3(target, l, m, n); // Mid-size, med of 3
}
int v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && target[b] <= v) {
if (target[b] == v)
swap(target, a++, b, coSort);
b++;
}
while (c >= b && target[c] >= v) {
if (target[c] == v)
swap(target, c, d--, coSort);
c--;
}
if (b > c)
break;
swap(target, b++, c--, coSort);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s, coSort);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s, coSort);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort1(target, fromIndex, s, coSort);
if ((s = d - c) > 1)
quickSort1(target, n - s, s, coSort);
}
private static void swap(int x[], int a, int b, long[] coSort) {
swap(x, a, b);
swap(coSort, a, b);
}
/**
* Swaps x[a] with x[b].
*/
private static void swap(long x[], int a, int b) {
long t = x[a];
x[a] = x[b];
x[b] = t;
}
private static void vecswap(int x[], int a, int b, int n, long[] coSort) {
for (int i = 0; i < n; i++, a++, b++)
swap(x, a, b, coSort);
}
/**
* Sorts the specified target array of objects into ascending order, according to the natural ordering of its
* elements and simultaneously permutes the {@code coSort} objects array in the same way then specified target
* array.
The code was taken from the jdk6 Arrays class.
The sorting algorithm is a tuned quicksort,
* adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function", Software-Practice and
* Experience, Vol. 23(11) P. 1249-1265 (November 1993). This algorithm offers n*log(n) performance on many data
* sets that cause other quicksorts to degrade to quadratic performance.
NOTE: this is unstable sort
* algorithm, so additional combinatorics of the {@code coSort} array can be perfomed. Use this method only if you
* are sure, in what you are doing. If not - use stable sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws IllegalArgumentException if coSort length less then target length.
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static > void quickSort(T[] target, Object[] coSort) {
quickSort(target, 0, target.length, coSort);
}
/**
* Sorts the specified target array of objects into ascending order, according to the natural ordering of its
* elements and simultaneously permutes the {@code coSort} objects array in the same way then specified target
* array. The range to be sorted extends from index fromIndex , inclusive, to index toIndex ,
* exclusive. (If fromIndex==toIndex , the range to be sorted is empty.)
The code was taken from the
* jdk6 Arrays class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas
* McIlroy's "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
* 1993). This algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to
* quadratic performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the
* {@code coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use
* stable sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static > void quickSort(T[] target, int fromIndex, int toIndex, Object[] coSort) {
if (target == coSort)
throw new IllegalArgumentException();
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
quickSort1(target, fromIndex, toIndex - fromIndex, coSort);
}
/**
* This method is the same as {@link #quickSort(Comparable[], int, int, Object[])}, but without range checking.
*
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code coSort} array can be
* perfomed. Use this method only if you are sure, in what you are doing. If not - use stable sort methods like an
* insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static > void quickSort1(T[] target, int fromIndex, int length, Object[] coSort) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && target[j - 1].compareTo(target[j]) > 0; j--)
swap(target, j, j - 1, coSort);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s);
m = med3(target, m - s, m, m + s);
n = med3(target, n - 2 * s, n - s, n);
}
m = med3(target, l, m, n); // Mid-size, med of 3
}
T v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && target[b].compareTo(v) <= 0) {
if (target[b] == v)
swap(target, a++, b, coSort);
b++;
}
while (c >= b && target[c].compareTo(v) >= 0) {
if (target[c] == v)
swap(target, c, d--, coSort);
c--;
}
if (b > c)
break;
swap(target, b++, c--, coSort);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s, coSort);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s, coSort);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort1(target, fromIndex, s, coSort);
if ((s = d - c) > 1)
quickSort1(target, n - s, s, coSort);
}
private static void swap(Object[] x, int a, int b, Object[] coSort) {
swap(x, a, b);
swap(coSort, a, b);
}
private static void vecswap(Object[] x, int a, int b, int n, Object[] coSort) {
for (int i = 0; i < n; i++, a++, b++)
swap(x, a, b, coSort);
}
/**
* Sorts the specified target array of objects into ascending order, according to the natural ordering of its
* elements and simultaneously permutes the {@code coSort} objects array in the same way then specified target
* array.
The code was taken from the jdk6 Arrays class.
The sorting algorithm is a tuned quicksort,
* adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function", Software-Practice and
* Experience, Vol. 23(11) P. 1249-1265 (November 1993). This algorithm offers n*log(n) performance on many data
* sets that cause other quicksorts to degrade to quadratic performance.
NOTE: this is unstable sort
* algorithm, so additional combinatorics of the {@code coSort} array can be perfomed. Use this method only if you
* are sure, in what you are doing. If not - use stable sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws IllegalArgumentException if coSort length less then target length.
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static > void quickSort(T[] target, int[] coSort) {
quickSort(target, 0, target.length, coSort);
}
/**
* Sorts the specified target array of objects into ascending order, according to the natural ordering of its
* elements and simultaneously permutes the {@code coSort} objects array in the same way then specified target
* array. The range to be sorted extends from index fromIndex , inclusive, to index toIndex ,
* exclusive. (If fromIndex==toIndex , the range to be sorted is empty.)
The code was taken from the
* jdk6 Arrays class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas
* McIlroy's "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
* 1993). This algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to
* quadratic performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the
* {@code coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use
* stable sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static > void quickSort(T[] target, int fromIndex, int toIndex, int[] coSort) {
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
quickSort1(target, fromIndex, toIndex - fromIndex, coSort);
}
/**
* This method is the same as {@link #quickSort(Comparable[], int, int, Object[])}, but without range checking.
*
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code coSort} array can be
* perfomed. Use this method only if you are sure, in what you are doing. If not - use stable sort methods like an
* insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if target == coSort (as references).
*/
public static > void quickSort1(T[] target, int fromIndex, int length, int[] coSort) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && target[j - 1].compareTo(target[j]) > 0; j--)
swap(target, j, j - 1, coSort);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s);
m = med3(target, m - s, m, m + s);
n = med3(target, n - 2 * s, n - s, n);
}
m = med3(target, l, m, n); // Mid-size, med of 3
}
T v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && target[b].compareTo(v) <= 0) {
if (target[b] == v)
swap(target, a++, b, coSort);
b++;
}
while (c >= b && target[c].compareTo(v) >= 0) {
if (target[c] == v)
swap(target, c, d--, coSort);
c--;
}
if (b > c)
break;
swap(target, b++, c--, coSort);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s, coSort);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s, coSort);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort1(target, fromIndex, s, coSort);
if ((s = d - c) > 1)
quickSort1(target, n - s, s, coSort);
}
private static void swap(Object[] x, int a, int b, int[] coSort) {
swap(x, a, b);
swap(coSort, a, b);
}
private static void vecswap(Object[] x, int a, int b, int n, int[] coSort) {
for (int i = 0; i < n; i++, a++, b++)
swap(x, a, b, coSort);
}
/**
* Swaps x[a] with x[b].
*/
public static void swap(Object[] x, int a, int b) {
Object t = x[a];
x[a] = x[b];
x[b] = t;
}
private static > int med3(T[] x, int a, int b, int c) {
return (x[a].compareTo(x[b]) < 0
? (x[b].compareTo(x[c]) < 0 ? b : x[a].compareTo(x[c]) < 0 ? c : a)
: (x[b].compareTo(x[c]) > 0 ? b : x[a].compareTo(x[c]) > 0 ? c : a));
}
/**
* Sorts the specified target array of ints into ascending numerical order and simultaneously permutes the {@code
* coSort} Objects array in the same way as the target array.
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static void quickSort(int[] target, Object[] coSort) {
quickSort1(target, 0, target.length, coSort);
}
/**
* Sorts the specified range of the specified target array of ints into ascending numerical order and simultaneously
* permutes the {@code coSort} Objects array in the same way as the target array. The range to be sorted
* extends from index fromIndex , inclusive, to index toIndex , exclusive. (If
* fromIndex==toIndex , the range to be sorted is empty.)
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static void quickSort(int[] target, int fromIndex, int toIndex, Object[] coSort) {
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
quickSort1(target, fromIndex, toIndex - fromIndex, coSort);
}
/**
* This method is the same as {@link #quickSort(int[], int, int, Object[]) ) }, but without range checking.
* NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code coSort} array can be
* perfomed. Use this method only if you are sure, in what you are doing. If not - use stable sort methods like an
* insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
*/
public static void quickSort1(int target[], int fromIndex, int length, Object[] coSort) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && target[j - 1] > target[j]; j--)
swap(target, j, j - 1, coSort);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s);
m = med3(target, m - s, m, m + s);
n = med3(target, n - 2 * s, n - s, n);
}
m = med3(target, l, m, n); // Mid-size, med of 3
}
int v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && target[b] <= v) {
if (target[b] == v)
swap(target, a++, b, coSort);
b++;
}
while (c >= b && target[c] >= v) {
if (target[c] == v)
swap(target, c, d--, coSort);
c--;
}
if (b > c)
break;
swap(target, b++, c--, coSort);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s, coSort);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s, coSort);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort1(target, fromIndex, s, coSort);
if ((s = d - c) > 1)
quickSort1(target, n - s, s, coSort);
}
private static void swap(int x[], int a, int b, Object[] coSort) {
swap(x, a, b);
swap(coSort, a, b);
}
private static void vecswap(int x[], int a, int b, int n, Object[] coSort) {
for (int i = 0; i < n; i++, a++, b++)
swap(x, a, b, coSort);
}
public static int[] quickSortP(short[] target) {
int[] permutation = new int[target.length];
for (int i = 1; i < target.length; ++i)
permutation[i] = i;
quickSort(target, 0, target.length, permutation);
return permutation;
}
/**
* Sorts the specified range of the specified target array of ints into ascending numerical order and simultaneously
* permutes the {@code coSort} ints array in the same way as the target array. The range to be sorted
* extends from index fromIndex , inclusive, to index toIndex , exclusive. (If
* fromIndex==toIndex , the range to be sorted is empty.)
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: remember this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
NOTE: The method throws {@code
* IllegalArgumentException} if {@code target == coSort}, because in this case no sorting will be perfomed.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static void quickSort(short[] target, int fromIndex, int toIndex, int[] coSort) {
rangeCheck(target.length, fromIndex, toIndex);
rangeCheck(coSort.length, fromIndex, toIndex);
quickSort1(target, fromIndex, toIndex - fromIndex, coSort);
}
/**
* This method is the same as {@link #quickSort(int[], int, int, int[]) }, but without range checking and toIndex ->
* length (see params). Throws {@code IllegalArgumentException} if {@code target == coSort}, because in this case no
* sorting will be perfomed .
NOTE: this is unstable sort algorithm, so additional combinatorics of the
* {@code coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use
* stable sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param coSort the array which will be permuted in the same way as the target array, during
* sorting procedure
*/
public static void quickSort1(short target[], int fromIndex, int length, int[] coSort) {
quickSort2(target, fromIndex, length, coSort);
}
private static void quickSort2(short target[], int fromIndex, int length, int[] coSort) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && target[j - 1] > target[j]; j--)
swap(target, j, j - 1, coSort);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s);
m = med3(target, m - s, m, m + s);
n = med3(target, n - 2 * s, n - s, n);
}
m = med3(target, l, m, n); // Mid-size, med of 3
}
int v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && target[b] <= v) {
if (target[b] == v)
swap(target, a++, b, coSort);
b++;
}
while (c >= b && target[c] >= v) {
if (target[c] == v)
swap(target, c, d--, coSort);
c--;
}
if (b > c)
break;
swap(target, b++, c--, coSort);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s, coSort);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s, coSort);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort2(target, fromIndex, s, coSort);
if ((s = d - c) > 1)
quickSort2(target, n - s, s, coSort);
}
/**
* Sorts the specified target array of shorts into ascending numerical order and simultaneously permutes the {@code
* coSort} ints array in the same way as the target array.
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: remember this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
NOTE: The method throws {@code
* IllegalArgumentException} if {@code target == coSort}, because in this case no sorting will be perfomed.
*
* @param target the array to be sorted
* @param coSort the array which will be permuted in the same way as the target array during sorting
* procedure
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static void quickSort(short[] target, int[] coSort) {
quickSort(target, 0, target.length, coSort);
}
private static void swap(short x[], int a, int b, int[] coSort) {
swap(x, a, b);
swap(coSort, a, b);
}
/**
* Swaps x[a] with x[b].
*/
private static void swap(short x[], int a, int b) {
short t = x[a];
x[a] = x[b];
x[b] = t;
}
private static void vecswap(short x[], int a, int b, int n, int[] coSort) {
for (int i = 0; i < n; i++, a++, b++)
swap(x, a, b, coSort);
}
/**
* Returns the index of the median of the three indexed integers.
*/
private static int med3(short x[], int a, int b, int c) {
return (x[a] < x[b]
? (x[b] < x[c] ? b : x[a] < x[c] ? c : a)
: (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
}
////////////////////////////////////// COMPARATOR /////////////////////////////////////////////////////
/**
* Sorts the specified range of the specified target array of ints into order specified by {@link IntComparator}
* using quicksort.
*
* @param target the array to be sorted
* @param comparator custom comparator
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static void quickSort(int[] target, IntComparator comparator) {
quickSort1(target, 0, target.length, comparator);
}
/**
* Sorts the specified range of the specified target array of ints into order specified by {@link IntComparator}
* using quicksort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param comparator comparator
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static void quickSort(int[] target, int fromIndex, int toIndex, IntComparator comparator) {
rangeCheck(target.length, fromIndex, toIndex);
quickSort1(target, fromIndex, toIndex - fromIndex, comparator);
}
/**
* Sorts the specified range of the specified target array of ints into order specified by {@link IntComparator}
* using quicksort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param comparator comparator
*/
public static void quickSort1(int target[], int fromIndex, int length, IntComparator comparator) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && comparator.compare(target[j - 1], target[j]) > 0; j--)
swap(target, j, j - 1);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s, comparator);
m = med3(target, m - s, m, m + s, comparator);
n = med3(target, n - 2 * s, n - s, n, comparator);
}
m = med3(target, l, m, n, comparator); // Mid-size, med of 3
}
int v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && comparator.compare(target[b], v) <= 0) {
if (comparator.compare(target[b], v) == 0)
swap(target, a++, b);
b++;
}
while (c >= b && comparator.compare(target[c], v) >= 0) {
if (comparator.compare(target[c], v) == 0)
swap(target, c, d--);
c--;
}
if (b > c)
break;
swap(target, b++, c--);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort1(target, fromIndex, s, comparator);
if ((s = d - c) > 1)
quickSort1(target, n - s, s, comparator);
}
/////////////////////////////// QUICK SORT INTCOMPARATOR COSORT ////////////////////////////////////////
/**
* Sorts the specified target array of ints according to {@link IntComparator} and simultaneously permutes the {@code
* coSort} Objects array in the same way as the target array.
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param comparator custom comparator
* @throws IllegalArgumentException if coSort length less then target length.
*/
public static void quickSort(int[] target, int[] cosort, IntComparator comparator) {
quickSort1(target, 0, target.length, cosort, comparator);
}
/**
* Sorts the specified range of the specified target array of ints according to {@link IntComparator} and simultaneously
* permutes the {@code coSort} Objects array in the same way as the target array. The range to be sorted
* extends from index fromIndex , inclusive, to index toIndex , exclusive. (If
* fromIndex==toIndex , the range to be sorted is empty.)
The code was taken from the jdk6 Arrays
* class.
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's
* "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This
* algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic
* performance.
NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code
* coSort} array can be perfomed. Use this method only if you are sure, in what you are doing. If not - use stable
* sort methods like an insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param toIndex the index of the last element (exclusive) to be sorted
* @param comparator comparator
* @throws IllegalArgumentException if fromIndex > toIndex
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or toIndex > target.length or
* toIndex > coSort.length
*/
public static void quickSort(int[] target, int fromIndex, int toIndex, int[] cosort, IntComparator comparator) {
rangeCheck(target.length, fromIndex, toIndex);
if (target == cosort)
throw new IllegalArgumentException("Same array references.");
quickSort1(target, fromIndex, toIndex - fromIndex, cosort, comparator);
}
/**
* This method is the same as {@link #quickSort(int[], int, int, Object[]) ) }, but without range checking.
* NOTE: this is unstable sort algorithm, so additional combinatorics of the {@code coSort} array can be
* perfomed. Use this method only if you are sure, in what you are doing. If not - use stable sort methods like an
* insertion sort or Tim sort.
*
* @param target the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be sorted
* @param length the length of the sorting subarray.
* @param comparator comparator
*/
private static void quickSort1(int target[], int fromIndex, int length, int[] cosort, IntComparator comparator) {
// Insertion quickSort on smallest arrays
if (length < 7) {
for (int i = fromIndex; i < length + fromIndex; i++)
for (int j = i; j > fromIndex && comparator.compare(target[j - 1], target[j]) > 0; j--)
swap(target, j, j - 1, cosort);
return;
}
// Choose a partition element, v
int m = fromIndex + (length >> 1); // Small arrays, middle element
if (length > 7) {
int l = fromIndex;
int n = fromIndex + length - 1;
if (length > 40) { // Big arrays, pseudomedian of 9
int s = length / 8;
l = med3(target, l, l + s, l + 2 * s, comparator);
m = med3(target, m - s, m, m + s, comparator);
n = med3(target, n - 2 * s, n - s, n, comparator);
}
m = med3(target, l, m, n, comparator); // Mid-size, med of 3
}
int v = target[m];
// Establish Invariant: v* (v)* v*
int a = fromIndex, b = a, c = fromIndex + length - 1, d = c;
while (true) {
while (b <= c && comparator.compare(target[b], v) <= 0) {
if (comparator.compare(target[b], v) == 0)
swap(target, a++, b, cosort);
b++;
}
while (c >= b && comparator.compare(target[c], v) >= 0) {
if (comparator.compare(target[c], v) == 0)
swap(target, c, d--, cosort);
c--;
}
if (b > c)
break;
swap(target, b++, c--, cosort);
}
// Swap partition elements back to middle
int s, n = fromIndex + length;
s = Math.min(a - fromIndex, b - a);
vecswap(target, fromIndex, b - s, s, cosort);
s = Math.min(d - c, n - d - 1);
vecswap(target, b, n - s, s, cosort);
// Recursively quickSort non-partition-elements
if ((s = b - a) > 1)
quickSort1(target, fromIndex, s, cosort, comparator);
if ((s = d - c) > 1)
quickSort1(target, n - s, s, cosort, comparator);
}
/**
* Returns the index of the median of the three indexed integers.
*/
private static int med3(int x[], int a, int b, int c, IntComparator comparator) {
return (comparator.compare(x[a], x[b]) < 0
? (comparator.compare(x[b], x[c]) < 0 ? b : comparator.compare(x[a], x[c]) < 0 ? c : a)
: (comparator.compare(x[b], x[c]) > 0 ? b : comparator.compare(x[a], x[c]) > 0 ? c : a));
}
private static void vecswap(int x[], int a, int b, int n) {
for (int i = 0; i < n; i++, a++, b++)
swap(x, a, b);
}
////////////////////////////////////// UTILS ///////////////////////////////////////////////////////////
/**
* Check that fromIndex and toIndex are in range, and throw an appropriate exception if they aren't.
*/
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex
+ ") > toIndex(" + toIndex + ")");
if (fromIndex < 0)
throw new ArrayIndexOutOfBoundsException(fromIndex);
if (toIndex > arrayLen)
throw new ArrayIndexOutOfBoundsException(toIndex);
}
public static String toString(T[] a, ToStringConverter format) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(format.toString(a[i]));
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
public static String toString(int[] a, ToStringConverter format) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(format.toString(a[i]));
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
}
Ads help maintain this website.