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

4 篇文章 0 订阅

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();
  • 技术交流群:679293162
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值