• Partial QuickSort in Java


    The Partial QuickSort algorithm was first introduced by Conrado Martínez in his paper "Partial QuickSort".

    Partial QuickSort works as follows. Like quicksort but in every recursive call we receive a subarray a[i..j] and a k that k >= i. We want to rearrange the subarray so that a[i..k] contains the k - i + 1 smallest elements of a[i, j] in ascending order; if k > j that means we must fully sort a[i..j].

    Pseudo code:
    function partial_quicksort(a, i, j, k)
        if i < j
            p ← partition(a, i, j)
            partial_quicksort(a, i, p-1, k)
            if p < k-1
                partial_quicksort(a, p+1, j, k)
     
    The expected running time of this algorithm is only O(n + m log m) where n is the size of the subarray a[i..j] and m is the number of smallest elements we need

    Java Code:
      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 = 32;
     20     
     21     public static <T> void partialSort(
     22             T[] a, int fromIndex, int toIndex, int middleIndex,
     23             Comparator<? super T> c) {
     24         rangeCheck(a.length, fromIndex, toIndex);
     25 
     26         int[] stack = new int[MAX_STACK_SIZE];
     27         int top = 0;
     28 
     29         stack[top++] = fromIndex;
     30         stack[top++] = toIndex;
     31 
     32         while (top > 0) {
     33             toIndex = stack[--top];
     34             fromIndex = stack[--top];
     35 
     36             if (toIndex - fromIndex <= INSERTION_SORT_THRESHOLD) {
     37                 for (int i = fromIndex + 1; i < toIndex; i++) {
     38                     T x = a[i];
     39                     int j = i;
     40                     while (--j >= fromIndex && c.compare(x, a[j]) < 0) {
     41                         a[j + 1] = a[j];
     42                     }
     43                     a[j + 1] = x;
     44                 }
     45                 continue;
     46             }
     47 
     48             int pivotIndex = partition(a, fromIndex, toIndex, c);
     49 
     50             if (pivotIndex - fromIndex >= toIndex - pivotIndex - 1) {
     51                 stack[top++] = fromIndex;
     52                 stack[top++] = pivotIndex;
     53 
     54                 if (pivotIndex < middleIndex - 1) {
     55                     stack[top++] = pivotIndex + 1;
     56                     stack[top++] = toIndex;
     57                 }
     58             } else {
     59                 if (pivotIndex < middleIndex - 1) {
     60                     stack[top++] = pivotIndex + 1;
     61                     stack[top++] = toIndex;
     62                 }
     63                 if (pivotIndex > fromIndex) {
     64                     stack[top++] = fromIndex;
     65                     stack[top++] = pivotIndex;
     66                 }
     67             }
     68         }
     69     }
     70 
     71     private static void rangeCheck(
     72             int arrayLength, int fromIndex, int toIndex) {
     73 
     74         if (arrayLength > MAX_ARRAY_SIZE) {
     75             throw new IllegalArgumentException("size of array (" +
     76                     arrayLength + ") is too large, maximum array " +
     77                     "size allowed: " + MAX_ARRAY_SIZE);
     78         }
     79 
     80         if (fromIndex < 0) {
     81             throw new ArrayIndexOutOfBoundsException(fromIndex);
     82         }
     83 
     84         if (toIndex > arrayLength) {
     85             throw new ArrayIndexOutOfBoundsException(toIndex);
     86         }
     87 
     88         if (fromIndex > toIndex) {
     89             throw new IllegalArgumentException(
     90                     "fromIndex(" + fromIndex + ") > " +
     91                             "toIndex(" + toIndex + ")");
     92         }
     93     }
     94 
     95     private static final long RANDOM_SEED = System.currentTimeMillis();
     96 
     97     private static <T> int partition(T[] a, int fromIndex, int toIndex,
     98                                      Comparator<? super T> c) {
     99         int n = toIndex - fromIndex;
    100         int pivotIndex = fromIndex + (n >> 1);
    101         if (n > MEDIAN_OF_THREE_THRESHOLD) {
    102             Random random = new Random(RANDOM_SEED);
    103             pivotIndex = medianOfThree(a,
    104                     fromIndex + random.nextInt(n),
    105                     fromIndex + random.nextInt(n),
    106                     fromIndex + random.nextInt(n),
    107                     c);
    108         }
    109         swap(a, fromIndex, pivotIndex);
    110 
    111         T pivot = a[fromIndex];
    112         int i = fromIndex;
    113         for (int j = fromIndex + 1; j < toIndex; j++) {
    114             if (c.compare(a[j], pivot) < 0) {
    115                 swap(a, ++i, j);
    116             }
    117         }
    118         swap(a, fromIndex, i);
    119         return i;
    120     }
    121 
    122     private static <T> int medianOfThree(T[] a, int i, int j, int k,
    123                                          Comparator<? super T> c) {
    124         return c.compare(a[i], a[j]) < 0 ?
    125                 (c.compare(a[j], a[k]) < 0 ? j :
    126                         c.compare(a[i], a[k]) < 0 ? k : i) :
    127                 (c.compare(a[k], a[j]) < 0 ? j :
    128                         c.compare(a[i], a[k]) < 0 ? i : k);
    129     }
    130 
    131     private static <T> void swap(T[] a, int i, int j) {
    132         T temp = a[i];
    133         a[i] = a[j];
    134         a[j] = temp;
    135     }
    136 
    137     public static <T> void sort(T[] a, Comparator<? super T> c) {
    138         sort(a, 0, a.length, c);
    139     }
    140 
    141     public static <T> void sort(T[] a, int fromIndex, int toIndex,
    142                                 Comparator<? super T> c) {
    143         partialSort(a, fromIndex, toIndex, toIndex, c);
    144     }
    145 
    146     public static <T> void partialSort(T[] a, int k,
    147                                        Comparator<? super T> c) {
    148         partialSort(a, 0, a.length, k, c);
    149     }
    150 }
    
    
  • 相关阅读:
    Linux0.11之初识Makefile/build.c
    主机(windows10)虚拟机(ubuntu18)arm板(linux3.4)相互ping通
    windows上利用dhcpsrv搭建DHCP服务器
    《剑指offer》面试题27 二叉搜索树与双向链表 Java版
    《剑指offer》面试题26 复杂链表的复制 Java版
    《剑指offer》面试题25 二叉树中和为某一值的路径 Java版
    《剑指offer》面试题24 二叉搜索树的后序遍历序列 Java版
    异常处理
    三元表达式、列表推导式、生成器表达式、匿名函数、内置函数、递归调用与二分法的简单认识
    迭代器与生成器
  • 原文地址:https://www.cnblogs.com/william-cheung/p/8893608.html
Copyright © 2020-2023  润新知