2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.util.Arrays;
24 import java.util.Comparator;
27 * A class to perform efficient sorting of arrays of objects based on arrays of
28 * scores or other attributes. For example, residues by percentage frequency.
33 public class QuickSort
35 static class FloatComparator implements Comparator<Integer>
38 private final float[] values;
40 FloatComparator(float[] v)
46 public int compare(Integer o1, Integer o2)
48 return Float.compare(values[o1], values[o2]);
53 static class IntComparator implements Comparator<Integer>
56 private final int[] values;
58 IntComparator(int[] v)
64 public int compare(Integer o1, Integer o2)
66 return Integer.compare(values[o1], values[o2]);
72 * Sorts both arrays with respect to ascending order of the items in the first
78 public static void sort(int[] arr, Object[] s)
80 sort(arr, 0, arr.length - 1, s);
84 * Sorts both arrays with respect to ascending order of the items in the first
90 public static void sort(float[] arr, Object[] s)
92 sort(arr, 0, arr.length - 1, s);
96 * Sorts both arrays with respect to ascending order of the items in the first
102 public static void sort(double[] arr, Object[] s)
104 sort(arr, 0, arr.length - 1, s);
108 * Sorts both arrays with respect to descending order of the items in the
114 public static void sort(String[] arr, Object[] s)
116 stringSort(arr, 0, arr.length - 1, s);
119 static void stringSort(String[] arr, int p, int r, Object[] s)
125 q = stringPartition(arr, p, r, s);
126 stringSort(arr, p, q, s);
127 stringSort(arr, q + 1, r, s);
131 static void sort(float[] arr, int p, int r, Object[] s)
137 q = partition(arr, p, r, s);
139 sort(arr, q + 1, r, s);
143 static void sort(double[] arr, int p, int r, Object[] s)
149 q = partition(arr, p, r, s);
151 sort(arr, q + 1, r, s);
155 static void sort(int[] arr, int p, int r, Object[] s)
161 q = partition(arr, p, r, s);
163 sort(arr, q + 1, r, s);
167 static int partition(float[] arr, int p, int r, Object[] s)
178 } while (arr[j] > x);
183 } while (arr[i] < x);
202 static int partition(float[] arr, int p, int r, char[] s)
213 } while (arr[j] > x);
218 } while (arr[i] < x);
237 static int partition(int[] arr, int p, int r, Object[] s)
248 } while (arr[j] > x);
253 } while (arr[i] < x);
272 static int partition(double[] arr, int p, int r, Object[] s)
283 } while (arr[j] > x);
288 } while (arr[i] < x);
307 static int stringPartition(String[] arr, int p, int r, Object[] s)
318 } while (arr[j].compareTo(x) < 0);
323 } while (arr[i].compareTo(x) > 0);
343 * Sorts both arrays to give ascending order in the first array, by first
344 * partitioning into zero and non-zero values before sorting the latter.
349 public static void sort(float[] arr, char[] s)
352 * Sort all zero values to the front
354 float[] f1 = new float[arr.length];
355 char[] s1 = new char[s.length];
356 int nextZeroValue = 0;
357 int nextNonZeroValue = arr.length - 1;
358 for (int i = 0; i < arr.length; i++)
363 f1[nextNonZeroValue] = val;
364 s1[nextNonZeroValue] = s[i];
369 f1[nextZeroValue] = val;
370 s1[nextZeroValue] = s[i];
376 * Copy zero values back to original arrays
378 System.arraycopy(f1, 0, arr, 0, nextZeroValue);
379 System.arraycopy(s1, 0, s, 0, nextZeroValue);
381 if (nextZeroValue == arr.length)
386 * Sort the non-zero values
388 float[] nonZeroFloats = Arrays
389 .copyOfRange(f1, nextZeroValue, f1.length);
390 char[] nonZeroChars = Arrays.copyOfRange(s1, nextZeroValue, s1.length);
391 externalSort(nonZeroFloats, nonZeroChars);
392 // sort(nonZeroFloats, 0, nonZeroFloats.length - 1, nonZeroChars);
395 * Assemble sorted non-zero results
397 System.arraycopy(nonZeroFloats, 0, arr, nextZeroValue,
398 nonZeroFloats.length);
399 System.arraycopy(nonZeroChars, 0, s, nextZeroValue, nonZeroChars.length);
403 * Sort by making an array of indices, and sorting it using a comparator that
404 * refers to the float values.
407 * ://stackoverflow.com/questions/4859261/get-the-indices-of-an-array-
412 protected static void externalSort(float[] arr, char[] s)
414 final int length = arr.length;
415 Integer[] indices = makeIndexArray(length);
416 Arrays.sort(indices, new FloatComparator(arr));
419 * Copy the array values as per the sorted indices
421 float[] sortedFloats = new float[length];
422 char[] sortedChars = new char[s.length];
423 for (int i = 0; i < length; i++)
425 sortedFloats[i] = arr[indices[i]];
426 sortedChars[i] = s[indices[i]];
430 * And copy the sorted values back into the arrays
432 System.arraycopy(sortedFloats, 0, arr, 0, length);
433 System.arraycopy(sortedChars, 0, s, 0, s.length);
437 * Make an array whose values are 0...length.
442 protected static Integer[] makeIndexArray(final int length)
444 Integer[] indices = new Integer[length];
445 for (int i = 0; i < length; i++)
452 static void sort(float[] arr, int p, int r, char[] s)
457 q = partition(arr, p, r, s);
459 sort(arr, q + 1, r, s);
464 * Sorts both arrays to give ascending order in the first array, by first
465 * partitioning into zero and non-zero values before sorting the latter.
470 public static void sort(int[] arr, char[] s)
473 * Sort all zero values to the front
475 int[] f1 = new int[arr.length];
476 char[] s1 = new char[s.length];
477 int nextZeroValue = 0;
478 int nextNonZeroValue = arr.length - 1;
479 for (int i = 0; i < arr.length; i++)
484 f1[nextNonZeroValue] = val;
485 s1[nextNonZeroValue] = s[i];
490 f1[nextZeroValue] = val;
491 s1[nextZeroValue] = s[i];
497 * Copy zero values back to original arrays
499 System.arraycopy(f1, 0, arr, 0, nextZeroValue);
500 System.arraycopy(s1, 0, s, 0, nextZeroValue);
502 if (nextZeroValue == arr.length)
507 * Sort the non-zero values
509 int[] nonZeroInts = Arrays
510 .copyOfRange(f1, nextZeroValue, f1.length);
511 char[] nonZeroChars = Arrays.copyOfRange(s1, nextZeroValue, s1.length);
512 externalSort(nonZeroInts, nonZeroChars);
513 // sort(nonZeroFloats, 0, nonZeroFloats.length - 1, nonZeroChars);
516 * Assemble sorted non-zero results
518 System.arraycopy(nonZeroInts, 0, arr, nextZeroValue, nonZeroInts.length);
519 System.arraycopy(nonZeroChars, 0, s, nextZeroValue, nonZeroChars.length);
523 * Sort by making an array of indices, and sorting it using a comparator that
524 * refers to the float values.
527 * ://stackoverflow.com/questions/4859261/get-the-indices-of-an-array-
532 protected static void externalSort(int[] arr, char[] s)
534 final int length = arr.length;
535 Integer[] indices = makeIndexArray(length);
536 Arrays.sort(indices, new IntComparator(arr));
539 * Copy the array values as per the sorted indices
541 int[] sortedInts = new int[length];
542 char[] sortedChars = new char[s.length];
543 for (int i = 0; i < length; i++)
545 sortedInts[i] = arr[indices[i]];
546 sortedChars[i] = s[indices[i]];
550 * And copy the sorted values back into the arrays
552 System.arraycopy(sortedInts, 0, arr, 0, length);
553 System.arraycopy(sortedChars, 0, s, 0, s.length);