Partial QuickSort in Java

Posted Escape The Well

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Partial QuickSort in Java相关的知识,希望对你有一定的参考价值。

  1 import java.util.Comparator;
  2 import java.util.Random;
  3 
  4 /**
  5  * Created by william on 08/04/2018.
  6  */
  7 public class QuickSort<T> {
  8 
  9     private static final int MAX_STACK_SIZE = 64;
 10     private static final int MAX_ARRAY_SIZE;
 11     static {
 12         long maxArraySize = 1L << (MAX_STACK_SIZE / 2 - 1);
 13         MAX_ARRAY_SIZE = (int) Math.min(
 14                 maxArraySize, (long) Integer.MAX_VALUE);
 15     }
 16 
 17     private static final int INSERTION_SORT_THRESHOLD = 16;
 18 
 19     private static final int MEDIAN_OF_THREE_THRESHOLD = 48;
 20 
 21     public static <T> void sort(T[] a, int fromIndex, int toIndex,
 22                                 Comparator<? super T> c) {
 23         partialSort(a, fromIndex, toIndex, toIndex, c);
 24     }
 25 
 26     /**
 27      * This method implements the Partial QuickSort introduced by
 28      * Conrado Martínez in his paper "Partial QuickSort".
 29      *
 30      *
 31      * - Pseudo Code ------------------------------------------------
 32      *
 33      *   function partial_quicksort(a, i, j, k)
 34      *       if i < j
 35      *           p ← partition(a, i, j)
 36      *           partial_quicksort(a, i, p-1, k)
 37      *           if p < k-1
 38      *               partial_quicksort(a, p+1, j, k)
 39      *
 40      * --------------------------------------------------------------
 41      *
 42      * Partial QuickSort works as follows. In every recursive call
 43      * we receive a subarray a[i..j] and a k that k >= i. We must
 44      * rearrange the subarray so that a[i..k] contains the k - i + 1
 45      * smallest elements of a[i, j] in ascending order; if k > j
 46      * that means we must fully sort a[i..j].
 47      *
 48      * This algorithm required an expected time of only O(n + m log m)
 49      * where n is the size of the subarray a[i..j] and m is the number
 50      * of smallest elements we need
 51      *
 52      * See http://www.lsi.upc.edu/~conrado/research/reports/ALCOMFT-TR-03-50.pdf
 53      *  for more details
 54      *
 55      */
 56     public static <T> void partialSort(
 57             T[] a, int fromIndex, int toIndex, int middleIndex,
 58             Comparator<? super T> c) {
 59         rangeCheck(a.length, fromIndex, toIndex);
 60 
 61         int[] stack = new int[MAX_STACK_SIZE];
 62         int top = 0;
 63 
 64         stack[top++] = fromIndex;
 65         stack[top++] = toIndex;
 66 
 67         while (top > 0) {
 68             toIndex = stack[--top];
 69             fromIndex = stack[--top];
 70 
 71             if (toIndex - fromIndex <= INSERTION_SORT_THRESHOLD) {
 72                 for (int i = fromIndex + 1; i < toIndex; i++) {
 73                     T x = a[i];
 74                     int j = i;
 75                     while (--j >= fromIndex && c.compare(x, a[j]) < 0) {
 76                         a[j + 1] = a[j];
 77                     }
 78                     a[j + 1] = x;
 79                 }
 80                 continue;
 81             }
 82 
 83             int pivotIndex = partition(a, fromIndex, toIndex, c);
 84 
 85             if (pivotIndex - fromIndex >= toIndex - pivotIndex - 1) {
 86                 stack[top++] = fromIndex;
 87                 stack[top++] = pivotIndex;
 88 
 89                 if (pivotIndex < middleIndex - 1) {
 90                     stack[top++] = pivotIndex + 1;
 91                     stack[top++] = toIndex;
 92                 }
 93             } else {
 94                 if (pivotIndex < middleIndex - 1) {
 95                     stack[top++] = pivotIndex + 1;
 96                     stack[top++] = toIndex;
 97                 }
 98                 if (pivotIndex > fromIndex) {
 99                     stack[top++] = fromIndex;
100                     stack[top++] = pivotIndex;
101                 }
102             }
103         }
104     }
105 
106     private static void rangeCheck(
107             int arrayLength, int fromIndex, int toIndex) {
108 
109         if (arrayLength > MAX_ARRAY_SIZE) {
110             throw new IllegalArgumentException("size of array is " +
111                     "too large, maximum array size allowed: " +
112                     MAX_ARRAY_SIZE);
113         }
114 
115         if (fromIndex < 0) {
116             throw new ArrayIndexOutOfBoundsException(fromIndex);
117         }
118 
119         if (toIndex > arrayLength) {
120             throw new ArrayIndexOutOfBoundsException(toIndex);
121         }
122 
123         if (fromIndex > toIndex) {
124             throw new IllegalArgumentException(
125                     "fromIndex(" + fromIndex + ") > " +
126                             "toIndex(" + toIndex + ")");
127         }
128     }
129 
130     private static final long RANDOM_SEED = System.currentTimeMillis();
131 
132     private static <T> int partition(T[] a, int fromIndex, int toIndex,
133                                      Comparator<? super T> c) {
134         int n = toIndex - fromIndex;
135         int pivotIndex = fromIndex + (n >> 1);
136         if (n > MEDIAN_OF_THREE_THRESHOLD) {
137             Random random = new Random(RANDOM_SEED);
138             pivotIndex = medianOfThree(a,
139                     fromIndex + random.nextInt(n),
140                     fromIndex + random.nextInt(n),
141                     fromIndex + random.nextInt(n),
142                     c);
143         }
144         swap(a, fromIndex, pivotIndex);
145 
146         T pivot = a[fromIndex];
147         int i = fromIndex;
148         for (int j = fromIndex + 1; j < toIndex; j++) {
149             if (c.compare(a[j], pivot) < 0) {
150                 swap(a, ++i, j);
151             }
152         }
153         swap(a, fromIndex, i);
154         return i;
155     }
156 
157     private static <T> int medianOfThree(T[] a, int i, int j, int k,
158                                          Comparator<? super T> c) {
159         return c.compare(a[i], a[j]) < 0 ?
160                 (c.compare(a[j], a[k]) < 0 ? j :
161                         c.compare(a[i], a[k]) < 0 ? k : i) :
162                 (c.compare(a[k], a[j]) < 0 ? j :
163                         c.compare(a[i], a[k]) < 0 ? i : k);
164     }
165 
166     private static <T> void swap(T[] a, int i, int j) {
167         T temp = a[i];
168         a[i] = a[j];
169         a[j] = temp;
170     }
171 
172     public static <T> void sort(T[] a, Comparator<? super T> c) {
173         sort(a, 0, a.length, c);
174     }
175 
176     public static <T> void partialSort(T[] a, int k,
177                                        Comparator<? super T> c) {
178         partialSort(a, 0, a.length, k, c);
179     }
180 }

 

以上是关于Partial QuickSort in Java的主要内容,如果未能解决你的问题,请参考以下文章

partial 函数

A Partial Lunar Eclipse Will Be Visible Tonight in China

Typescript的高级tricks(in,keyof,Partial,Pick,Exclude等)

Some features we need to keep in mind about the implementation of QuickSort algorithm

Quicksort与就地合并排序

QuickSort