zoukankan      html  css  js  c++  java
  • Java查找算法之二分查找

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

    一、算法思想

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

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

    二、举例图示

      要查找的数为21。

      第一次将头指针和尾指针分别放置头尾,middle放在中间。将21与中间的56进行比较。21<56,应在左边。

      第二次将尾指针放在56得到前一位,middle放在中间。将21与中间的19进行比较。21>19,应在右边。

      第三次将头指针放在19的后一位,middle放在中间。将21与21比较,符合查找成功!

    三、二分查找优缺点及使用条件

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

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

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

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

    四、算法实现

     1 package recursion;
     2 
     3 /**
     4  * @author zsh
     5  * @company wlgzs
     6  * @create 2019-02-16 10:11
     7  * @Describe 二分查找的两种实现
     8  */
     9 public class BinarySearch {
    10 
    11     /**
    12      * 循环实现二分查找
    13      * @param arr 待查找的数组
    14      * @param key 待查找的数
    15      * @return key在数组中的索引位置
    16      */
    17     static int binary1(int[] arr,int key){
    18         //头指针初始位置
    19         int low = 0;
    20         //尾指针初始位置
    21         int high = arr.length -1;
    22         //定义middle指针位置
    23         int middle = 0;
    24         //头尾交叉 || key大于最大值 || key小于最小值,说明未找到
    25         if (low > high || key > arr[high] || key < arr[low]){
    26             return -1;
    27         }
    28 
    29         while (low <= high){
    30             //防止数据溢出
    31             middle = (low + high) >>> 1;
    32             if (arr[middle] > key){
    33                 //middle所对应的值比key大,key应该在左边区域
    34                 high = middle -1;
    35             }else if (arr[middle] < key){
    36                 //middle所对应的值比key小,key应该在有边区域
    37                 low = middle +1;
    38             }else {
    39                 return middle;
    40             }
    41 
    42         }
    43 
    44         //最后仍然没有找到,则返回-1
    45         return -1;
    46     }
    47 
    48     /**
    49      * 递归实现二分查找
    50      * @param arr 待查找的数组
    51      * @param low 头指针所在位置
    52      * @param high 尾指针所在位置
    53      * @param key 待查找的数
    54      * @return key在数组中的索引位置
    55      * 算法分析:
    56      * 找重复:
    57      * 找变化量:
    58      * 找出口:头尾交叉 || key大于最大值 || key小于最小值
    59      */
    60     static int binary2(int[] arr,int low , int high ,int key){
    61 
    62         //头尾交叉 || key大于最大值 || key小于最小值,说明未找到
    63         if (low > high || key > arr[high] || key < arr[low]){
    64             return -1;
    65         }
    66         //定义middle指针位置,防止数据溢出
    67         int middle = (low + high) >>> 1;
    68 
    69         //middle所对应的值比key大,key应该在左边区域
    70         if (arr[middle] > key){
    71             binary2(arr,low,middle-1,key);
    72         }else if (arr[middle] < key){
    73             //middle所对应的值比key小,key应该在有边区域
    74             binary2(arr,low+1,high,key);
    75         }else {
    76             return middle;
    77         }
    78 
    79         //最后仍然没有找到,则返回-1
    80         return -1;
    81     }
    82 
    83     public static void main(String[] args) {
    84         int[] arr = new int[]{5,13,19,21,37,56,64,75,80,88,92};
    85         System.out.println(binary1(arr,21));
    86         System.out.println(binary1(arr,21));
    87     }
    88 
    89 }

     五、时间复杂度和空间复杂度

      时间复杂度

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

        最好情况下O(1)

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

        非递归方式

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

        递归方式

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

  • 相关阅读:
    Extjs combobox设置默认值
    sql 游标循环遍历
    .NET中的DES对称加密
    Asp.Net生命周期
    浅谈C#随机数发生器
    面向对象-多态 附抽象
    c#常用的一些命名空间
    c#面向对象编程基础
    string应用
    [自习任我行]第二阶段任务跟踪10
  • 原文地址:https://www.cnblogs.com/zsh-blogs/p/10387028.html
Copyright © 2011-2022 走看看