vlambda博客
学习文章列表

传说中的二分查找和快速排序

1、二分查找

/* 二分查找(折半查找),前提是在已经排好序的数组中 通过将待查找的元素与中间索引值对应的元素进行比较, 若大于中间索引值对应的元素,去右半部分查找,否则去左半部分查找 一次类推,知道找到位置 */public class Test8{    public static void main(String[] args){    
        int[] nums={10,20,50,65,88,90};//待查找数组
        int index= binarySearch(nums,90);
        System.out.println(index);
    }    //二分查找数列
    public static int binarySearch(int[] num,int key){        int start=0;//开始下标
        int end=num.length-1;//结束下标

        while(start<=end){            int middle=(start+end)/2;//>>>1
            if(num[middle]>key){
                end=middle-1;
            }else if(num[middle]<key){
                start=middle+1;
            }else{                return middle;
            }
        }        return -1;

    }

}

其实这个二分查找在JDK里也有的,JDk已经帮我们写好了,嘻嘻,但是我们也得知道它怎么查找的是不是!

2、Arrays类

专门用来操作数组的一个类,我们只介绍几种常用的方法

  • 使用二分法查找
    我们每当学习别人的代码的时候,我们一定要先看文档看API文档,这个类有什么方法,每个方法是干啥的,全整的明明白白!上图,呸,上文档!
    文档下载地址下载完解压,然后有个API文件夹,打开index,就是你想要的东西,见证奇迹的时候到了!


然后咱找找,Arrays

传说中的二分查找和快速排序

传说中的二分查找和快速排序
哎,是不是看到了一个熟悉的方法,就是咱们刚刚写的那个方法binarySearch(),二分查找,那我们看一样JDK里的二分查找怎么是实现的呢,咱们去遛一眼源码去!gogogo去JDK SRC目录下,util包里有一个Arrays类打开看看吧!

传说中的二分查找和快速排序
这个方法没有提供具体的实现,但是它调了一个binarySearch0()这个方法

传说中的二分查找和快速排序看这个方法,思路是不是和我们的思路一样呢!

  • 数组内容转成字符串的形式输出
    你看我们在上一篇博客中,查看数组内容是怎么查看的呢,是遍历遍历的时候挨个输出,但是我们有了Array这个类后,就很方便了嘛!


这个也是遍历,然后拼接起来了,看起来更好看一点!

  • 数组排序


Arrys里的排序是用的什么排序呢Quicksort快速排序,looklook快排的源码!

    /* * Sorting methods for seven primitive types. */

    /** * Sorts the specified range of the array using the given * workspace array slice if possible for merging * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted * @param work a workspace array (slice) * @param workBase origin of usable space in work array * @param workLen usable size of work array */
    static void sort(int[] a, int left, int right, int[] work, int workBase, int workLen) {        // Use Quicksort on small arrays
        if (right - left < QUICKSORT_THRESHOLD) {
            sort(a, left, right, true);            return;
        }        /* * Index run[i] is the start of i-th run * (ascending or descending sequence). */
        int[] run = new int[MAX_RUN_COUNT + 1];        int count = 0; run[0] = left;        // Check if the array is nearly sorted
        for (int k = left; k < right; run[count] = k) {            if (a[k] < a[k + 1]) { // ascending
                while (++k <= right && a[k - 1] <= a[k]);
            } else if (a[k] > a[k + 1]) { // descending
                while (++k <= right && a[k - 1] >= a[k]);                for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {                    int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                }
            } else { // equal
                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {                    if (--m == 0) {
                        sort(a, left, right, true);                        return;
                    }
                }
            }            /* * The array is not highly structured, * use Quicksort instead of merge sort. */
            if (++count == MAX_RUN_COUNT) {
                sort(a, left, right, true);                return;
            }
        }        // Check special cases
        // Implementation note: variable "right" is increased by 1.
        if (run[count] == right++) { // The last run contains one element
            run[++count] = right;
        } else if (count == 1) { // The array is already sorted
            return;
        }        // Determine alternation base for merge
        byte odd = 0;        for (int n = 1; (n <<= 1) < count; odd ^= 1);        // Use or create temporary array b for merging
        int[] b;                 // temp array; alternates with a
        int ao, bo;              // array offsets from 'left'
        int blen = right - left; // space needed for b
        if (work == null || workLen < blen || workBase + blen > work.length) {
            work = new int[blen];
            workBase = 0;
        }        if (odd == 0) {
            System.arraycopy(a, left, work, workBase, blen);
            b = a;
            bo = 0;
            a = work;
            ao = workBase - left;
        } else {
            b = work;
            ao = 0;
            bo = workBase - left;
        }        // Merging
        for (int last; count > 1; count = last) {            for (int k = (last = 0) + 2; k <= count; k += 2) {                int hi = run[k], mi = run[k - 1];                for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {                    if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
                        b[i + bo] = a[p++ + ao];
                    } else {
                        b[i + bo] = a[q++ + ao];
                    }
                }
                run[++last] = hi;
            }            if ((count & 1) != 0) {                for (int i = right, lo = run[count - 1]; --i >= lo;
                    b[i + bo] = a[i + ao]
                );
                run[++last] = right;
            }            int[] t = a; a = b; b = t;            int o = ao; ao = bo; bo = o;
        }
    }

代码很长,有兴趣的同学可以研究研究逻辑!

  • 复制指定的数组
Arrays.copyOf(int[] array, int length);//int 返回新数组的长度 
        Arrays.copyOf(int[] array, int from, int to); //复制某一段
        System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));        return copy;
    }

由此得出,数组复制效率由高到低排序是System.arraycopy>Arrays.copyOf

  • 判断两个数组是否相等Arrays.equels();
  • 使用指定元素填充数组Arrays.fill();