简单算法——二分查找法

二分查找算法二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。

但是,前提是查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

查找过程

首先,假设数组中元素是按升序排列,将数组中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将数组分成前、后两个子数组,如果中间位置记录的关键字大于查找关键字,则进一步查找前一数组,否则进一步查找后一数组。重复以上过程,直到找到满足条件的记录,使查找成功,或直到数组不存在为止,此时查找不成功。

下面我们测试一下:

/**
     * 二分查找
     * @param arr 元素组
     * @param num 查询数据
     * @return 返回脚标
     */
    public static int binarySearch(int [] arr,int num){

        //起始脚标
            int start = 0;
            //末尾脚标
            int end = arr.length -1;
            while(start <= end){
                //获取中间脚标
                int middleindex = (start+ end)/2;
                //  拿中间位置数据 与传递数据进行比较
                if(num < arr[middleindex]){
                    //如果中间位置数据 大于当前数据 则将end 设置为中间位置减一
                    end = middleindex - 1;
                }else if(num > arr[middleindex]){
                    //如果中间位置数据 大于当前数据 则将start 设置为中间位置加一
                    start = middleindex+1;
                }else {
                    //等于 直接命中 返回脚标
                    return middleindex;
                }
            }

        return -1;
    }

    /**
     * 普通查找
     * @param arr 元素组
     * @param num 查询数据
     * @return 返回脚标
     */
    public static int simpleSearch(int [] arr,int num){
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == num ){
                return i;
            }
        }
        return -1;
    }
  • 设定起始查询脚标为0,结束脚标为数组长度减一。
  • 将数据进行循环,首次获取中间位置(int 会强制转换成整数型,不用担心除不尽)。
  • 拿中间位置数据 与传递数据进行比较 如果中间位置数据 大于当前数据 则将end 设置为中间位置减一
  • 如果中间位置数据 大于当前数据 则将start 设置为中间位置加一
  • 等于 直接命中 返回脚标

创建一个200000000大小的数组测试一下和普通查询的效率差距:

//创建一个200000000大小的数组

    public static void main(String[] args) {
        int [] arr = new int[200000000];

        for (int i = 0; i < 200000000; i++) {
            arr[i] = i ;
        }

        Arrays.sort(arr);
        Instant startTime = Instant.now();
        int i = binarySearch(arr, 190000000);
        Instant endTime = Instant.now();
        System.out.println(i);
        System.out.println("二分查询:" +Duration.between(startTime,endTime).toMillis()+"ms");

        Instant start = Instant.now();
        int i1 = simpleSearch(arr, 190000000);
        System.out.println(i1);
        Instant end = Instant.now();
        System.out.println("遍历查询:"  + Duration.between(start,end).toMillis()+"ms");
    }
190000000
二分查询:0ms
190000000
遍历查询:82ms

可以看到差距比想象中打的惊人。
因为:二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果xa[n/2],则只要在数组a的右半部搜索x.

时间复杂度无非就是while循环的次数!

总共有n个元素,

渐渐跟下去就是n,n/2,n/4,…n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数

由于你n/2^k取整后>=1

即令n/2^k=1

可得k=log2n,(是以2为底,n的对数)

所以时间复杂度可以表示O(h)=O(log2n)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值