smile.sort.QuickSort Maven / Gradle / Ivy
/******************************************************************************
* Confidential Proprietary *
* (c) Copyright Haifeng Li 2011, All Rights Reserved *
******************************************************************************/
package smile.sort;
import java.util.Comparator;
/**
* Quicksort is a well-known sorting algorithm that, on average, makes O(n log n)
* comparisons to sort n items. For large n (say > 1000), Quicksort is faster,
* on most machines, by a factor of 1.5 or 2 than other O(n log n) algorithms.
* However, in the worst case, it makes O(n2) comparisons. Quicksort
* requires a bit of extra memory.
*
* Quicksort is a comparison sort. A comparison sort is a type of sorting
* algorithm that only reads the list elements through a single abstract
* comparison operation (often a "less than or equal to" operator) that
* determines which of two elements should occur first in the final sorted list.
* The only requirement is that the operator obey the three defining properties
* of a total order:
*
* - if a ≤ b and b ≤ a then a = b (antisymmetry)
*
- if a ≤ b and b ≤ c then a ≤ c (transitivity)
*
- a ≤ b or b ≤ a (totalness or trichotomy)
*
*
* Quicksort, however, is not a stable sort in efficient implementations.
* Stable sorting algorithms maintain the relative order of records with
* equal keys. If all keys are different then this distinction is not
* necessary. But if there are equal keys, then a sorting algorithm is
* stable if whenever there are two records(let's say R and S) with the
* same key, and R appears before S in the original list, then R will
* always appear before S in the sorted list.
*
* For speed of execution, we implement it without recursion. Instead,
* we requires an auxiliary array (stack) of storage, of length
* 2 log2 n. When a subarray has gotten down to size 7,
* we sort it by straight insertion.
*
* @author Haifeng Li
*/
public class QuickSort {
private static final int M = 7;
private static final int NSTACK = 64;
/**
* Sorts the specified array into ascending numerical order.
* @return the original index of elements after sorting in range [0, n).
*/
public static int[] sort(int[] arr) {
int[] order = new int[arr.length];
for (int i = 0; i < order.length; i++) {
order[i] = i;
}
sort(arr, order);
return order;
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(int[] arr, int[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(int[] arr, int[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k, a, b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(int[] arr, Object[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(int[] arr, Object[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k, a;
Object b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Sorts the specified array into ascending numerical order.
* @return the original index of elements after sorting in range [0, n).
*/
public static int[] sort(float[] arr) {
int[] order = new int[arr.length];
for (int i = 0; i < order.length; i++) {
order[i] = i;
}
sort(arr, order);
return order;
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(float[] arr, int[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(float[] arr, int[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
float a;
int b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(float[] arr, float[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(float[] arr, float[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
float a, b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(float[] arr, Object[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(float[] arr, Object[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
float a;
Object b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Sorts the specified array into ascending numerical order.
* @return the original index of elements after sorting in range [0, n).
*/
public static int[] sort(double[] arr) {
int[] order = new int[arr.length];
for (int i = 0; i < order.length; i++) {
order[i] = i;
}
sort(arr, order);
return order;
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(double[] arr, int[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(double[] arr, int[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
double a;
int b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(double[] arr, double[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(double[] arr, double[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
double a, b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static void sort(double[] arr, Object[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(double[] arr, Object[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
double a;
Object b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i] <= a) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l] > arr[ir]) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1] > arr[ir]) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l] > arr[l + 1]) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i] < a);
do {
j--;
} while (arr[j] > a);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Sorts the specified array into ascending order.
* @return the original index of elements after sorting in range [0, n).
*/
public static > int[] sort(T[] arr) {
int[] order = new int[arr.length];
for (int i = 0; i < order.length; i++) {
order[i] = i;
}
sort(arr, order);
return order;
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static > void sort(T[] arr, int[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static > void sort(T[] arr, int[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
T a;
int b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i].compareTo(a) <= 0) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l].compareTo(arr[ir]) > 0) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1].compareTo(arr[ir]) > 0) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l].compareTo(arr[l + 1]) > 0) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i].compareTo(a) < 0);
do {
j--;
} while (arr[j].compareTo(a) > 0);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static void sort(T[] arr, int[] brr, int n, Comparator comparator) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
T a;
int b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (comparator.compare(arr[i], a) <= 0) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (comparator.compare(arr[l], arr[ir]) > 0) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (comparator.compare(arr[l + 1], arr[ir]) > 0) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (comparator.compare(arr[l], arr[l + 1]) > 0) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (comparator.compare(arr[i], a) < 0);
do {
j--;
} while (comparator.compare(arr[j], a) > 0);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
/**
* Besides sorting the array arr, the array brr will be also
* rearranged as the same order of arr.
*/
public static > void sort(T[] arr, Object[] brr) {
sort(arr, brr, arr.length);
}
/**
* This is an effecient implementation Quick Sort algorithm without
* recursive. Besides sorting the first n elements of array arr, the first
* n elements of array brr will be also rearranged as the same order of arr.
*/
public static > void sort(T[] arr, Object[] brr, int n) {
int jstack = -1;
int l = 0;
int[] istack = new int[NSTACK];
int ir = n - 1;
int i, j, k;
T a;
Object b;
for (;;) {
if (ir - l < M) {
for (j = l + 1; j <= ir; j++) {
a = arr[j];
b = brr[j];
for (i = j - 1; i >= l; i--) {
if (arr[i].compareTo(a) <= 0) {
break;
}
arr[i + 1] = arr[i];
brr[i + 1] = brr[i];
}
arr[i + 1] = a;
brr[i + 1] = b;
}
if (jstack < 0) {
break;
}
ir = istack[jstack--];
l = istack[jstack--];
} else {
k = (l + ir) >> 1;
SortUtils.swap(arr, k, l + 1);
SortUtils.swap(brr, k, l + 1);
if (arr[l].compareTo(arr[ir]) > 0) {
SortUtils.swap(arr, l, ir);
SortUtils.swap(brr, l, ir);
}
if (arr[l + 1].compareTo(arr[ir]) > 0) {
SortUtils.swap(arr, l + 1, ir);
SortUtils.swap(brr, l + 1, ir);
}
if (arr[l].compareTo(arr[l + 1]) > 0) {
SortUtils.swap(arr, l, l + 1);
SortUtils.swap(brr, l, l + 1);
}
i = l + 1;
j = ir;
a = arr[l + 1];
b = brr[l + 1];
for (;;) {
do {
i++;
} while (arr[i].compareTo(a) < 0);
do {
j--;
} while (arr[j].compareTo(a) > 0);
if (j < i) {
break;
}
SortUtils.swap(arr, i, j);
SortUtils.swap(brr, i, j);
}
arr[l + 1] = arr[j];
arr[j] = a;
brr[l + 1] = brr[j];
brr[j] = b;
jstack += 2;
if (jstack >= NSTACK) {
throw new IllegalStateException("NSTACK too small in sort.");
}
if (ir - i + 1 >= j - l) {
istack[jstack] = ir;
istack[jstack - 1] = i;
ir = j - 1;
} else {
istack[jstack] = j - 1;
istack[jstack - 1] = l;
l = i;
}
}
}
}
}