• 算法之查找


    1. Java语言二分查找代码实现

    public class Test {
      public static void main(String[] args) {
          // 准备好一个有序的被查找数组
          int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
          // 调用查找方法查找给定数组中5元素所在的索引值,并接收查找到的索引
          int index = getIndex(arr, 5);
          // 输出索引
          System.out.println("index:" + index);
      }
    
      public static int getIndex(int[] arr, int num) {
          // 定义变量,表示查找数组范围的最左侧,先从0索引开始
          int left = 0; 
          // 定义变量,表示查找数组范围的最右侧,先从最大索引开始
          int right = arr.length - 1;
          // 定义变量,表示查找范围的中间值
          int mid;
          while (left <= right) {
              // 中间索引 = (左侧  + 右侧) / 2
              // mid = (left + right) / 2; 
              // 为了提高效率,我们可以用位运算代替除以运算
              mid = (left + right) >>> 2 
              if (arr[mid] > num) {
                  //如果中间元素大于要查找元素,则在中间元素的左侧去找正确元素,最右侧变为mid - 1
                  right = mid - 1;
              } else if (arr[mid] < num) {
                  //如果中间元素小于要查找元素,则在中间元素的右侧去找正确元素,最左侧变为mid + 1
                  left = mid + 1;
              } else {
                  // 如果不大不小,那么就正好是找到了,返回找到的索引
                  return mid;
              }
          }
          // 当查找范围的最左侧和最右侧重叠后还没有找到元素,则返回-1表示没有找到
          return -1;
      }
    }

    控制台输出:index:4

    总结

           到目前为止我们已经用Java实现了二分查找。二分查找是一种相对简单而且比较高效的查找算法了,它的局限性就是被查找的数据需要有序。

    那么对其他查找算法感兴趣的小伙伴还可以去自行了解, 哈希查找,斐波那契查找等。 

     
    1.java实现二分查找-两种方式

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

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

    二分查找算法思想

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

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

    二分查找图示说明

     
    image.png

    二分查找优缺点

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

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

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

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

    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)

     
    image.png

    最好情况下为O(1)

    空间复杂度

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

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

    递归方式:

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

     
     
     
  • 相关阅读:
    OpenCascade Ray Tracing Rendering
    Create New Commands in Tcl
    OpenCascade Modeling Algorithms Fillets and Chamfers
    OpenCascade Modeling Algorithms Boolean Operations
    Construction of Primitives in Open Cascade
    Open Cascade Data Exchange STL
    Tcl Tk Introduction
    Open Cascade DataExchange IGES
    Netgen mesh library : nglib
    Hello Netgen
  • 原文地址:https://www.cnblogs.com/awkflf11/p/12578752.html
Copyright © 2020-2023  润新知