数据结构和算法————二分查找

                二分查找

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

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

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

      首先说一下二分查找的思想:假设数据是按升序排序的,对于给定值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;

  } 

    到此二分查找结束。

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

    想看的人可以看看 ^_^

      

      

时间: 2024-12-25 18:19:23

数据结构和算法————二分查找的相关文章

[数据结构与算法] : 二分查找

1 #include <stdio.h> 2 3 #define NotFound -1; 4 typedef int ElementType; 5 6 int BinarySearch( const ElementType A[], ElementType X, int N ) 7 { 8 int Low, Mid, High; 9 10 Low = 0; High = N-1; 11 while( Low <= High ) // 注意终止条件 12 { 13 Mid = (Low

查找算法-二分查找

查找算法-二分查找 标题 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. 过程 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找

数据结构与算法14—查找

查找 基本概念 查找就是在数据集中找出一个“特定元素”. 查找表是由同一类型的数据元素(或记录)构成的集合. 查找表是一种以集合为逻辑结构.以查找为核心的数据结构. 关键字 有时候我们需要指定某数据项的值来查找,这就用到了关键字. 关键字是数据元素中某个数据项的值,用以标识一个数据元素. 若此关键字可以识别唯一的一个记录,则称之谓“主关键字”:若此关键字能识别若干记录,则称之谓“次关键字”. 例: 对查找表经常进行的操作: 1)查询某个“特定的”数据元素是否在查找表中: 2)检索某个“特定的”数

[经典算法] 二分查找

题目说明: 二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回对应的数组下标,失败返回-1. 题目解析: 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表. 二分查找可以解决(预排序数组的查找)问题:只要数组中包含T(即要查找的值),那么通过不断缩小包含T的范围,最终就可以找到它.其算法流程如下: 1.一开始,范围覆盖整个数组. 2

检索算法——二分查找

如果要查找的数据是有序的, 二分查找算法比顺序查找算法更高效. function insertionSort(arr) { var temp, inner; for ( var outer = 1; outer < arr.length; ++outer) { temp = arr[outer]; //选中一个值作为临时值,使得其前面的数依次与它进行比较 inner = outer; while (inner > 0 && (arr[inner - 1] >= temp)

算法----二分查找算法

二分查找算法是在有序数组中用到的较为频繁的一种算法,在未接触二分查找算法时,最通用的一种做法是,对数组进行遍历,跟每个元素进行比较,其时间为O(n).但二分查找算法则更优,因为其查找时间为O(lgn),譬如数组{1, 2, 3, 4, 5, 6, 7, 8, 9},查找元素6,用二分查找的算法执行的话,其顺序为: 1.第一步查找中间元素,即5,由于5<6,则6必然在5之后的数组元素中,那么就在{6, 7, 8, 9}中查找, 2.寻找{6, 7, 8, 9}的中位数,为7,7>6,则6应该在7

莫对算法/二分查找 FZU 2072 Count

题目传送门 1 /* 2 题意:问区间内x的出现的次数 3 莫队算法:用一个cnt记录x的次数就可以了 4 还有二分查找的方法 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cmath> 9 #include <cstring> 10 using namespace std; 11 12 const int MAXN = 1e5 + 10; 13 const int INF = 0x3

八大排序算法二分查找

import java.util.ArrayList;import java.util.Arrays;import java.util.List; import org.junit.Test; public class InsertSort { public static void display(int[] arr){ System.out.print("["); for(int i=0;i<arr.length;i++){ if(i == arr.length-1){ Sys

算法-二分查找

二分查找算法是在有序数组中用到的较为频繁的一种算法,同样是一种很高效的算法,我们最长遇到的判断一个数字是不是在数组中,前提是数组是有效的,通常我们会数组进行遍历,跟每个元素进行比较,其时间为O(n).但二分查找算法则更优,因为其查找时间为O(lgn),譬如数组{0,1, 2, 3, 4, 5, 6, 7, 8, 9},查找元素3,用二分查找的算法执行的话,其顺序为:    1.第一步查找中间元素,即4,由于4>3,则3必然在4之前的数组元素中,那么就在{0,1, 2, 3}中查找,    2.寻