zoukankan      html  css  js  c++  java
  • 数据结构和算法————二分查找

                    二分查找

          这些天深刻的体会到了巩固知识的重要性。对数据结构和算法的学习有一年的时间,然后搁置了一年,最后发现都忘记了

          不过还好不是失忆,看了之前做过的笔记,还是能回想起来的。

          现在想在写一遍,算是对本子上的笔记做一个备份,更重要的是加深我的印象。 

          首先说一下二分查找的思想:假设数据是按升序排序的,对于给定值val,从序列的中间位置开始比较。

                       如果当前位置值等于val,则查找成功;

                       若val小于当前位置值,则在数列的前半段中查找

                       若val大于当前位置值,则在数列的后半段中继续查找。

                       重复以上步骤,直到找到为止。   

            这里我实现两种查找方式:

          1   二分查找的非递归实现

          2  二分查找的递归实现

           第一种 :二分查找的非递归实现

      /*
          author:Embarce
          param: int arr   待查找的数组,该数组要求是有序的,该段程序针对的是升序的数组
          param: int n     数组的长度
          param: int val   要查找的值
          return:int index 该值在数组中的下标 ,如果没有找到相应的值,返回-1 
      */
      int search(int arr[],int n,int val){
     
           int  left = 0;
           int right = n-1;
           int index = -1;
           int i;
        
    for( i = 0; i < n; i++ ){        int mid = (left + right) / 2;      if( arr[mid] == val ){       index = mid; }else if( arr[mid] > val){       right = mid -1;      }else{      left = mid + 1;       } }    return index;   }

          

         第二种 :二分查找的递归实现

    /*
        author:Embarce
        param: int left  查找区间的左下标 
        param: int right 查找区间的右下标 
        param: int arr   待查找的数组,该数组要求是有序的,该段程序针对的是升序数组
        param: int n     数组的长度
        param: int val   要查找的值
        return:int index 该值在数组中的下标 ,如果没有相应的值,返回-1 
    */
    int search(int left,int right,int arr[],int val){
    
       int mid;
       int index = -1;
       
       if(left > right)  
            
         return index;
          
       else{
            
            mid= (left + right) / 2;
            
            if( arr[mid] == val ){
                    index = mid;
                    return index; 
                    
            }else if( arr[mid] > val){
                    
                 right =  mid -1;
                 return search(left,right,arr,val);  
                   
            }else{
                 
                 left = mid + 1;
                 return search(left,right,arr,val); 
                    
            }
        }
      
    }

          

       二分查找的两种实现方式已经写完了。我只写了数组的,链式的二分查找和数组思想一样,有兴趣的可以自己去实现。

        然后在补充刚刚在书上看到的一个题:一个二维数组,每一行从左到右按照递增的方式排序,每一列从上往下递增按照得方式排序。输入一个数,判断这个数是否存在于二维数组。

       我这里就直接说一下解决方案,当然你也可以自己先思考有哪些解决方案,然后在看我下面写的是否和你想的一样。

       例如:二维数组arr

       1   2   3   4    5

       6   7   8   9    10

        11  12     13     14      15

        16  17   18   19     20

       输入的要查找的数为7

       我们选取右上角的数5为基准,因为5比7小,且5是第一行最大且索引位置最靠后的数,因此判断5所在的这一行从5的位置往左肯定不包含7,所以可以剔除5所在的这一整行。

       之后数组如下:

       6   7   8   9   10

        11  12     13     14      15

        16  17   18   19     20

       接着,我们在选取右上角的数10为基准,因为10比7大,且10是最后一列索引位置最靠前且最小的数,因此判断10这一列往下肯定不包含7,所以可以剔除10所在的这一整列。

         之后数组如下:

       6   7   8   9   

        11  12     13     14      

        16  17   18   19 

       接着,我们在选取右上角的数9为基准,因为9比7大,且9是最后一列索引位置最靠前且最小的数,因此判断9这一列往下肯定不包含7,所以可以剔除9所在的这一整列。

         之后数组如下:

       6   7   8      

        11  12     13          

        16  17   18   

        

       接着,我们在选取右上角的数8为基准,因为8比7大,且8是最后一列索引位置最靠前且最小的数,因此判断8这一列往下肯定不包含7,所以可以剔除8这一列。

        之后数组如下:

       6   7        

        11  12              

        16  17 

       最后选取 7为基准,也就是说找到了对应的值。

       问题到此解决完毕。

       其实我们也可以选择左下角的数为基准然后去分析,最终也可以找到相对应的值,这里我就不做分析了。

       然后现在的疑问就是为什么不选择左上角和右下角。

       我们现在就尝试一下选取左下脚为基准,即选取1为基准,1比7小,1也是它所在行的最小值,1也是它所在列的最小值。因此没办法判断到底该剔除那一列或者哪一行。

       同样在尝试右下脚,即以20为基准,20比7大,20同样是它所在行和所在列的最大值,同样我们也没有办法判断到底该剔除那一列或者哪一行。

       那么什么时候选取左下右上,什么时候选取左上右下呢。我想大家应该有了自己的答案。

           就是当二维数组行列都是升序的情况选择左下右上,行列都是降序的情况选择左上右下。

       现在附上具体的代码实现。

      

    /*
        author:Embarce
        param:int arr 待查找的数组,该数组要求是有序的 
        param:int row_length   数组的行数 
        param:int col_length   数组的列数 
        param:int val 要查找的值
        return:int rs 找到了返回1,没找到返回0
    */
    int search(int arr[4][6],int row_length,int col_length,int val){
     
      int rs = 0;
      int tmp = 0;
      int row_index = 0;
      int col_index = col_length-1;  
      
      while(row_index < row_length && col_index < col_length){
            
           tmp = arr[row_index][col_index];
    if(tmp == val){ rs = 1; break; }else if(tmp< val){ row_index = row_index+1; }else{ col_index = col_index-1; } } return rs; }

        到此二分查找结束。

        后面还补充了一个非二分但是属于查找类型题。

        想看的人可以看看 ^_^ 

     

          

          

  • 相关阅读:
    从Pycharm说起
    前端工程师小A学习JS的旅程
    模板引擎开发(一)
    Bootstrap01
    Passbook详解与开发案例
    DLL文件知多少?
    C#中的索引器的简单理解和用法
    python 的列表遍历删除
    Node.js与Golang使用感受与小结1
    解决设计中的两难问题
  • 原文地址:https://www.cnblogs.com/HouJiao/p/5563687.html
Copyright © 2011-2022 走看看