package jef.tools.algorithm; import java.util.Arrays; /** * 常用算法工具BFPRT * 线性查找算法 * * @author jiyi * */ public class BFPRT { /** * * @param a * @param id * @return */ public static <T extends Comparable<T>> T get(T[] a, int id) { return get(a,0,a.length,id); } /** * BFPRT算法实现—— 在传入的数组中,获得第id个序号的数值。 序号从1开始。 求数组a下标l到r中的第id个数 * * @param a * @param fromIndex * @param toIndex * @param id * @return */ public static <T extends Comparable<T>> T get(T[] a, int fromIndex, int toIndex, int id) { // 小于等于5个数,直接排序得到结果 if (toIndex - fromIndex <= 5) { Arrays.sort(a, fromIndex, toIndex); return a[fromIndex + id - 1]; } int t = fromIndex - 1; // 当前替换到前面的中位数的下标 for (int st = fromIndex, ed; (ed = st + 5) <= toIndex; st += 5) // 每5个进行处理 { Arrays.sort(a, st, ed); // 5个数的排序 t++; swap(a, t, st + 2); // 将中位数替换到数组前面,便于递归求取中位数的中位数 } int pivotId = (fromIndex + t) >> 1; // l到t的中位数的下标,作为主元的下标 get(a, fromIndex, t, pivotId - fromIndex + 1);// 不关心中位数的值,保证中位数在正确的位置 int m = partition(a, fromIndex, toIndex, pivotId), cur = m - fromIndex + 1; if (id == cur) return a[m]; // 刚好是第id个数 else if (id < cur) return get(a, fromIndex, m, id);// 第id个数在左边 else return get(a, m + 1, toIndex, id - cur); // 第id个数在右边 } private static void swap(Object[] a, int t, int i) { Object tmp = a[t]; a[t] = a[i]; a[i] = tmp; } // 对数组a下标从l到r的元素进行划分 private static <T extends Comparable<T>> int partition(T[] a, int l, int r, int pivotId) { // 以pivotId所在元素为划分主元 swap(a, pivotId, --r); int j = l - 1; // 左边数字最右的下标 for (int i = l; i < r; i++) if (a[i].compareTo(a[r]) <= 0) swap(a, ++j, i); swap(a, ++j, r); return j; } }