Advertisement
Guest User

Untitled

a guest
Aug 19th, 2019
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.75 KB | None | 0 0
  1. /*
  2. * Copyright 2013, 2014 Brenden Towey
  3. */
  4.  
  5. package SimpleUtils.sort;
  6.  
  7. import java.util.Comparator;
  8.  
  9. /** Sort utilities.
  10. *
  11. * @author Brenden Towey
  12. */
  13. public class Sort
  14. {
  15.  
  16. /**
  17. * Sorts an array of Comparable. Null values are moved to the end of the
  18. * array by this routine, so arrays containing null values can be safely
  19. * sorted.
  20. *
  21. * @param <T> Any Comparable.
  22. * @param table The array to be sorted.
  23. * @return The number of non-null elements in the array.
  24. */
  25. public static <T extends Comparable<? super T>> int sort( T[] table )
  26. {
  27. int newLength = moveNullsToEnd( table );
  28. quickSort( table, Comparator.naturalOrder(), 0, newLength - 1 );
  29. return newLength;
  30. }
  31.  
  32. /**
  33. * Moves null values to the end of an array. This is done in
  34. * preparation for sorting to remove nulls from the array. The
  35. * idea of moving nulls to the end of an array is synonymous with compacting
  36. * the array by moving all non-null elements to the beginning.
  37. *
  38. * <p>This method returns the number of non-null elements in the array.
  39. * The index of the last non-null element will be the one less than the
  40. * return value.
  41. *
  42. * @param table Table to move nulls to end.
  43. * @return The number of non-null elements.
  44. */
  45. public static int moveNullsToEnd( Object[] table )
  46. {
  47. int end = table.length-1;
  48. for( int i = 0 ;; ) {
  49. while( i < table.length && table[i] != null ) i++;
  50. if( i == table.length ) break;
  51. while( table[end] == null ) end--;
  52. if( i < end ) {
  53. table[i] = table[end];
  54. table[end] = null;
  55. } else
  56. break;
  57. }
  58. return end+1;
  59. }
  60.  
  61. /**
  62. * A quicksort implementation for arrays. Null values are not checked by
  63. * this method. Therefore a "null safe" Comparator must be used, such
  64. * as {@code Comparator.nullsFirst()}, or the array range to be sorted
  65. * must be free of nulls.
  66. *
  67. * @param <T> Any type.
  68. * @param comp A Comparator for T.
  69. * @param table An array of T to sort.
  70. * @param first First element in the (sub) array to sort, inclusive.
  71. * @param last Last element in the (sub) array to sort, inclusive.
  72. */
  73. public static <T> void quickSort( T[] table, Comparator<T> comp, int first,
  74. int last )
  75. {
  76. // System.out.println( "first="+first+", last="+last+" table="+Arrays.deepToString( table ) );
  77.  
  78. // The value of INSERT is empirically determined. Basically smaller values
  79. // are assumed to be better, up to a point, then they get worse.
  80. // In testing, sort times are quite close, differing only by few
  81. // tens of milliseconds over one million elements.
  82. // 10 is used here as it "theorectically" should be good all other
  83. // things being equal, and its times were generally smaller than other
  84. // numbers, although only slightly.
  85.  
  86. final int INSERT = 10;
  87.  
  88. if( last - first < INSERT )
  89. insertionSort( table, comp, first, last );
  90. else {
  91. int pivot = partition( table, comp, first, last );
  92. quickSort( table, comp, first, pivot - 1 );
  93. quickSort( table, comp, pivot + 1, last );
  94. }
  95. }
  96.  
  97. /**
  98. * A stable insertion sort. This routine does not check for nulls before
  99. * sorting. Therefore a "null-safe" comparator must be used, such as
  100. * {@code Comparator.nullsLast()}, or the array range must be free of
  101. * null values.
  102. *
  103. * @param <T> Any type.
  104. * @param table An array to be sorted.
  105. * @param comp A Comparator to use.
  106. * @param first The first element to sort, inclusive.
  107. * @param last The last element to sort, inclusive.
  108. *
  109. * @throws ArrayIndexOutOfBoundsException if either first or last are beyond the
  110. * bounds of the array table.
  111. * @throws NullPointerException if the array contains nulls and a "null-safe"
  112. * Comparator is not used.
  113. *
  114. * @throws NullPointerException if table or any element is null.
  115. */
  116. public static <T> void insertionSort( T[] table, Comparator<T> comp,
  117. int first, int last )
  118. {
  119. for( int i = first+1; i < last+1; i++ ) {
  120. T temp = table[i];
  121. int j = i-1;
  122. for( ; (j >= 0) && comp.compare( table[j], temp ) > 0; j-- ) {
  123. table[j+1] = table[j];
  124. }
  125. table[j+1] = temp;
  126. }
  127. }
  128.  
  129. /**
  130. * Partition for quicksort.
  131. *
  132. * @param <T> Any type.
  133. * @param table An array to sort.
  134. * @param comp Comparator to use.
  135. * @param first Index of first element to sort, inclusive.
  136. * @param last Index of last element to sort, inclusive.
  137. * @return
  138. */
  139. private static <T> int partition( T[] table, Comparator<T> comp, final int first,
  140. final int last )
  141. {
  142. int pivotIndex = getPivotIndex( table, comp, first, last );
  143. T pivot = table[ pivotIndex ];
  144. swap( table, first, pivotIndex );
  145.  
  146. int lower = first+1;
  147. int upper = last;
  148. do {
  149. while( (lower < upper) && comp.compare( pivot, table[lower] ) >= 0 )
  150. lower++;
  151. while( comp.compare( pivot, table[upper] ) < 0 )
  152. upper--;
  153. if( lower < upper )
  154. swap( table, lower, upper );
  155. } while( lower < upper );
  156. swap( table, first, upper );
  157. return upper;
  158. }
  159.  
  160. /**
  161. * Finds a pivot index by comparing up to nine values, to
  162. * determine the middle of those nine.
  163. *
  164. * @param <T> This works out to "anything that is Comparable"
  165. * @param table Array of Comparable.
  166. * @param first index of array to start looking for pivot.
  167. * @param last index of array of last value to consider for pivot.
  168. * @return The index of the pivot to use.s
  169. */
  170. private static <T> int getPivotIndex( T[] table, Comparator<T> comp,
  171. int first, int last )
  172. {
  173. int middle = (last+first) >>> 1; // divide by 2
  174.  
  175. // if less than 9 total just return the middle one
  176. if( last - first < 9 ) return middle;
  177.  
  178. // compute an offset to create a wider range of values
  179. int offset = (last-first) >>> 3; // divide by 8
  180.  
  181. // if 9 or more then we have nine values we can consider
  182. int mid1 = mid( table, comp, first, first + offset, first + offset * 2 );
  183. int mid2 = mid( table, comp, middle - offset, middle, middle + offset );
  184. int mid3 = mid( table, comp, last, last - offset, last - offset * 2 );
  185. return mid( table, comp, mid1, mid2, mid3 );
  186. }
  187.  
  188. /**
  189. * Find the middle value out of three, for an array of Comparable.
  190. *
  191. * @param <T> Any type with a Comparator.
  192. * @param table A table of type T.
  193. * @param comp A Comparator for type T.
  194. * @param first index of first element to compare.
  195. * @param second index of second element to compare.
  196. * @param third index of third element to compare.
  197. * @return index of middle element.
  198. */
  199. // package private for testing
  200. static <T> int mid( T[] table, Comparator<T> comp, int first, int second, int third )
  201. {
  202. T firstv = table[first];
  203. T secondv = table[second];
  204. T thirdv = table[third];
  205.  
  206. // return (a > b) ^ (a > c) ? a : (a > b) ^ (b > c) ? c : b;
  207. boolean aGTb = comp.compare( firstv, secondv ) > 0;
  208. boolean aGTc = comp.compare( firstv, thirdv ) > 0;
  209. boolean bGTc = comp.compare( secondv, thirdv ) > 0;
  210.  
  211. return (aGTb ^ aGTc) ? first : (aGTb ^ bGTc) ? third : second;
  212. }
  213.  
  214. /**
  215. * Swaps two references in an array.
  216. *
  217. * @param table Array to swap elements.
  218. * @param s1 index of first element to swap.
  219. * @param s2 index of second element to swap.
  220. *
  221. * @throws IndexOutOfBoundsException if either index is outside of the
  222. * bounds of the array.
  223. */
  224. public static void swap( Object[] table, int s1, int s2 ) {
  225. Object temp = table[s1];
  226. table[s1] = table[s2];
  227. table[s2] = temp;
  228. }
  229. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement