JDK中二分查找应用

本文详细解析了二分查找算法的原理与应用,探讨了其在JDK中的具体实现,包括Arrays类和Collections类的使用场景。介绍了算法的运行机制,以及在不同数据结构上的性能表现。

使用场景

  • 要查找的元素集必须有序。
  • 只需判断要查找的元素是否在集合中,对元素的位置无要求,因为如果元素在集合中有重复,则无法保证找到的是哪个。

JDK中的应用

  • Arrays类
   private static int binarySearch0(long[] a, int fromIndex, int toIndex, long key) {
		int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;//相当于 /2,位运算效率高
            long midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
	}
  • Collections类
    private static final int BINARYSEARCH_THRESHOLD   = 5000;
    public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
    	//列表元素支持随机快速访问的(如ArrayList)或者元素个数小于5000进行索引获取元素
    	//RandomAccess接口可以看做一个标志,实现了此接口的类,采用遍历方式效率高,相反,实现了Sequence List的类使用迭代器效率高
    	//对List特别是大量数据需要遍历的时候,推荐先判断是否实现了RandomAccess接口来选取最高效的遍历方式
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);//元素数>=5000或者实现了sequence List则使用迭代器获取元素
    }

对于索引查找元素

    //和数组遍历方式类似
    private static <T> int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
        int low = 0;
        int high = list.size()-1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            Comparable<? super T> midVal = list.get(mid);
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found
    }

通过迭代器查找元素

    private static <T> int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
    {
        int low = 0;
        int high = list.size()-1;
        ListIterator<? extends Comparable<? super T>> i = list.listIterator();//获得双向列表迭代器

        while (low <= high) {
            int mid = (low + high) >>> 1;
            Comparable<? super T> midVal = get(i, mid);//通过双向列表迭代器获取指定索引的元素值
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found
    }
    private static <T> T get(ListIterator<? extends T> i, int index) {
        T obj = null;
        int pos = i.nextIndex();
        if (pos <= index) { //指定索引位于迭代器后边则迭代器由开始位置逐步向后移动直至到指定索引位置
            do {
                obj = i.next();
            } while (pos++ < index);
        } else { //指定索引位于迭代器前边则迭代器由开始位置逐步向前移动直至到指定索引位置
            do {
                obj = i.previous();
            } while (--pos > index);
        }
        return obj;
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值