折半查找(二分查找)

折半查找(二分查找)

以下是本人的看完下面这一视频后的心得体会,该文章内容大致分为:折半查找的核心以及视频的折半查找与408课本上的折半查找的区别.如果看不懂的地方可以先看下面这位大佬的二分查找为什么总是写错?_哔哩哔哩_bilibili,再回过头来看该文章。若有错误的地方忘各位友友指出!!!🥳🥳🥳
  1. 折半查找的思路很简单,但问题出在细节上,对mid的值时常要么越界,要么是low或者high不知怎么初始化,或是low = mid还是low = mid + 1等问题。

  2. 这边的解决方法是:将小于key的值抽象为蓝色区域大于key的值抽象为红色区域,我们的目标找到mid抽象为找到蓝色区域和红色区域的蓝红边界,因为蓝红边界一定在mid对应的值的左边或者右边。因此等于key的判断会影响蓝红边界时在mid对应的值的左边还是右边

  3. 该方法与以往方法不同在于:它将key直接归并到两个区域的其中一个,最终在区域的蓝色区域右边第一个元素或者红色区域左边第一个元素找key。

在这里插入图片描述

  1. 代码分为2个部分
  • bool IsBlue(int A[], int key, int mid):其作用就是判断当前mid是在蓝色区域还是红色区域。——具体意义就是判断mid对应的值小于key还是等于key。如果是408考试,命名为bool LessThanKey(int A[], int key, in mid) 注意!!!IsBlue的定义为影响key在蓝色区域还是在红色区域
  • int Binary_Search(int A[], int key, int r):二分查找。
细节分析
  1. 为什么l的初始值为-1,r的初始值为N呢?
  • 假如l初始化为0,且数组全在红色区域(也就是元素值都大于key),那么一开始初始化l = 0就错了,因为l本身的定义是蓝色区域的边界(也就是元素值小于key);同理加入r = N - 1,且数组全在蓝色区域 ,也是错的。

在这里插入图片描述

  1. mid是否始终处于[0,N)以内?只有mid指向这个范围内才有意义。==这个边界问题常常容易犯错,就是因为mid没有在这一范围内(当然我说的是本人哈😆)==看下面的图
  • 这样就会获得mid的最小值为0

在这里插入图片描述

  • 这样就会获得mid的最大值为N-1,范围也就确定下来了,因此不会溢出且能表示数组所有元素。

在这里插入图片描述

  1. 更新指针时,能不能写成l = mid + 1r = mid - 1?——这种写法很容易导致细节上的错误
  • mid刚好指向蓝色区域最后一个元素(蓝色区域也就是小于等于key),那么l = mid + 1就会超过范围,导致找错红蓝界限;同理r = mid - 1也是一样的

在这里插入图片描述

在这里插入图片描述

  1. 程序会不会陷入死循环?(3种情况分析)
  • l + 1 = rl下一个就是r,while循环体会立马退出
    在这里插入图片描述

  • l + 2 = rlr之间间隔了一个元素,那么mid表示的就是该元素,因此下一步要么是r = mid,要么是l = mid ,就会回到l + 1 = r

在这里插入图片描述

在这里插入图片描述

  • l + 3 = rlr之间间隔了2个元素,那么mid表示的就是l的下一个元素,因此下一步要么是r = mid,要么是l = mid ,就会回到l + 2 = r

在这里插入图片描述

  • 依次类推所有情况都不会导致死循环
回到上面高亮部分说IsBlue的定义等于key会影响key会在蓝色区域还是红色区域的问题
  1. 当定义为A[mid] <= key时,如果存在key,那么key最终就会出现在蓝色区域;如果A[mid] < key,那么key最终就会出现在红色区域:以下代码也就是视频种的代码。如果是408考试,命名为bool LessThanKey(int A[], int key, in mid)
//作用:小于等于目标的为蓝色,大于目标的为红色————注意!!!等于这里很有考究哪一边有等于,最后二分查找返回哪一边的下标
//蓝色是左边,对应的就是l;红色是右边,对应的就是r
bool IsBlue(int A[], int mid, int key){
    if(A[mid] <= key)return true;	
    return false;
}

int BinarySearch(int A[], int key, int r){
    int l = -1, mid;
    while(l + 1 != r){
        mid = (l + r) / 2;     
        if(IsBlue(A, mid, key))l = mid;
        else r = mid;
    }
    //最后再判断以下l对应的值是否等于目标函数
    if(A[l] == key)return l;	//有则放回key的下标
    return -1;					//没有返回-1
}
  1. 教材上的代码

分析:midmin = 0, midmax = N -1,不会越界,但high和low改变指针有可能会导致细节错误

int Binary_Search(int A[], int key, int high){
    int low = 0, mid;
    while(low <= high){
        mid = (low + high) / 2;
        if(A[mid] == key)return mid;
        else if(A[mid] > key)high = mid - 1;
        else low = mid + 1;
    }
    return -1;
}
//**************************************教材方法******************************************************//

int main(){
    int A[11] = {7, 10, 13,16,19,29, 32,33,37, 41,43};
    
    int key = 32;
    int index = BinarySearch(A, key, sizeof(A) / sizeof(A[0]));
    cout<<index<<endl;

    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值