zoukankan      html  css  js  c++  java
  • 二分查找(java)

    二分查找是一种查询效率非常高的查找算法。又称折半查找。

    起初在数据结构中学习递归时实现二分查找,实际上不用递归也可以实现,毕竟递归是需要开辟额外的空间的来辅助查询。本文就介绍两种方法

    二分查找算法思想

    有序的序列,每次都是以序列的中间位置的数来与待查找的关键字进行比较,每次缩小一半的查找范围,直到匹配成功。


    一个情景:将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。


    比如说有一个1-100的数字,我随机的选择其中一个数字(假设为60),你需要以最少的次数猜到我所选择的数字,每次猜测后,我会告诉你大了,小了,对了。

    假设你第一次从1开始猜,小了

    第二次:2  小了

    第三次:3  小了

    ……

    第五十九次:59 小了

    第六十次:60 对了

    这是简单的查找,每次猜测只能排除一个数字,如果我想的数字是100,那么你可能需要从1猜到100了!

    那么有没有更好的查找方式呢?

    答案当然是有的。

    如果我选的数字是60

    第一次:你从50开始猜,那么我告诉你小了,就排除了接近一半的数字,因为你至少知道1-50都小了

    第二次:你猜75,那么我告诉你大了,这样剩下的数字又少了一半!或许你已经想到了,我们每次猜测都是选择了中间的那个数字,从而使得每次都将余下的数字排除了一半。

    第三次:接下来,很明显应该猜测63,大了

    第四次:然后你猜56,小了

    第五次:然后你猜59 小了

    第六次:猜测61,大了

    第七次,你就能很明确的告诉我,答案是60!

    这样的查找方式,很明显比第一种要高效很多。第一种需要猜测60次才能猜出正确答案,而使用第二种方式,只需要七次就能猜出正确答案

    或许看到这里你已经明白了,这就是二分查找的方法。为什么二分查找要求有序,从这里也可以看出来。一般而言,对于包含n个元素的列表,用二分查找最多需要logn步,而简单查找最多需要n步。

    二分查找优缺点


    优点是比较次数少,查找速度快,平均性能好

    其缺点是要求待查表为有序表,且插入删除困难

    因此,折半查找方法适用于不经常变动而查找频繁的有序列表。


    使用条件:查找序列是顺序结构,有序。

    java代码实现
    使用递归实现

      /**
         * 使用递归的二分查找
         * title:recursionBinarySearch
         *
         * @param arr 有序数组
         * @param key 待查找关键字
         * @return 找到的位置
         */
        public static int recursionBinarySearch(int[] arr, int key, int low, int high) {
    
            if (key < arr[low] || key > arr[high] || low > high) {
                return -1;
            }
    
            int middle = (low + high) / 2;    //初始中间位置
            if (arr[middle] > key) {
                //比关键字大则关键字在左区域
                return recursionBinarySearch(arr, key, low, middle - 1);
            } else if (arr[middle] < key) {
                //比关键字小则关键字在右区域
                return recursionBinarySearch(arr, key, middle + 1, high);
            } else {
                return middle;
            }
        }

    不使用递归实现(while循环)

       /**
         * 不使用递归的二分查找
         * title:commonBinarySearch
         *
         * @param arr
         * @param key
         * @return 关键字位置
         */
        public static int commonBinarySearch(int[] arr, int key) {
            int low = 0;
            int high = arr.length - 1;
            int middle = 0;    //定义middle
    
            if (key < arr[low] || key > arr[high] || low > high) {
                return -1;
            }
    
            while (low <= high) {
                middle = (low + high) / 2;
                if (arr[middle] > key) {
             //比关键字大则关键字在左区域
                  high = middle - 1;
                } else if (arr[middle] < key) {
              //比关键字小则关键字在右区域
                    low = middle + 1;
                } else {
                    return middle;
                }
            }
            return -1;    //最后仍然没有找到,则返回-1
        }

    测试
    测试代码:

    public static void main(String[] args){
        int[]arr={1,3,5,7,9,11};
        int key=4;
        //int position = recursionBinarySearch(arr,key,0,arr.length - 1);
        int position=commonBinarySearch(arr,key);
        if(position==-1){
        System.out.println("查找的是"+key+",序列中没有该数!");
        }else{
        System.out.println("查找的是"+key+",找到位置为:"+position);
        }
    }

    recursionBinarySearch()的测试:key分别为0,9,10,15的查找结果
    查找的是0,序列中没有该数!

    查找的是9,找到位置为:4

    查找的是10,序列中没有该数!

    查找的是15,序列中没有该数!

    commonBinarySearch()的测试:key分别为-1,5,6,20的查找结果

    查找的是-1,序列中没有该数!

    查找的是5,找到位置为:2

    查找的是6,序列中没有该数!

    查找的是20,序列中没有该数!


    时间复杂度
    采用的是分治策略

    最坏的情况下两种方式时间复杂度一样:O(log2 N)

    最好情况下为O(1)

    空间复杂度
      算法的空间复杂度并不是计算实际占用的空间,而是计算整个算法的辅助空间单元的个数

    非递归方式:
      由于辅助空间是常数级别的所以:
      空间复杂度是O(1);

    递归方式:

     递归的次数和深度都是log2 N,每次所需要的辅助空间都是常数级别的:
     空间复杂度:O(log2N )
    ————————————————

    参考:
    https://blog.csdn.net/zmeilin/article/details/81139814
    https://blog.csdn.net/maoyuanming0806/article/details/78176957

  • 相关阅读:
    Martix工作室考核题 —— 打印一个菱形
    Martix工作室考核题 —— 打印一个菱形
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第一题
    fiddler模拟发送post请求
  • 原文地址:https://www.cnblogs.com/ynyhl/p/11883199.html
Copyright © 2011-2022 走看看