二分总结

总结一下二分法的情况

本篇不能完全保证正确性。如有错误,请多多指教。

普通的binary_search

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int N = 10000;
int n = 10, d[N] = {0,1,1,2,2,3,5,6,7,7,10};
#define DF int l = 1, r = m, mid
#define sear_0  while(l <= r) {\
                    mid = l + ((r-l) >> 1);\
                    if(key == d[mid]) return mid;\
                    if(key < d[mid]) r = mid-1;\
                    else l = mid+1;\
                }
#define sear_1  while(l <= r) {\
                    mid = l + ((r-l) >> 1);\
                    if(key <= d[mid]) r = mid-1;\
                    else l = mid+1;\
                }
#define sear_2  while(l <= r) {\
                    mid = l + ((r-l) >> 1);\
                    if(key < d[mid]) r = mid-1;\
                    else l = mid+1;\
                }

void pt(int a) {
    printf("%d\n", a);
}

//_0 原始版 是否存在
int bin_0(int a[], int m, int key) {
    DF;
    sear_0
    return -1;
}

//_1_1 返回大于等于key的左端点
int bin_1_1(int a[], int m, int key) {
    DF;
    sear_1
    return l <= m ? l : -1;
}

//_1_2 返回大于key的左端点
int bin_1_2(int a[], int m, int key) {
    DF;
    sear_2
    return l <= m ? l : -1;
}

//_2_1 返回小于等于key的右端点(由大于key的左端点得到)
int bin_2_1(int a[], int m, int key) {
    DF;
    sear_2
    return l-1 > 0 ? l-1 : -1;
}

//_2_2 返回小于key的右端点(由大于等于key的左端点得到)
int bin_2_2(int a[], int m, int key) {
    DF;
    sear_1
    return l-1 > 0 ? l-1 : -1;
}

//_3_1 返回等于key的左端点(由大于等于key的左端点得到) 
int bin_3_1(int a[], int m, int key) {
    DF;
    sear_1
    return (l <= m) && (a[l] == key) ? l : -1;
}

//_3_2 返回等于key的右端点(由大于key的左端点得到) 
int bin_3_2(int a[], int m, int key) {
    DF;
    sear_2
    return (l-1 > 0) && (a[l-1] == key) ? l-1 : -1;
} 

int main() {
    int t;
    scanf("%d", &t);
    pt(bin_0(d, n, t));
    pt(bin_1_1(d, n, t)); pt(bin_1_2(d, n, t));
    pt(bin_2_1(d, n, t)); pt(bin_2_2(d, n, t));
    pt(bin_3_1(d, n, t)); pt(bin_3_2(d, n, t));
    return 0;
}

有自定义判断函数的binary_search

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

bool judge(int x) {} // 满足返回true,否则返回false 

//最小值(下界),即满足条件的最小值 ,可据上文 "_3_1 返回等于key的左端点" 得到 
//此时 judge() 的意义是大于等于下界的值都满足,小于下界的值不满足
//类比上文 key <= d[mid] 
int binary_down(int left, int right) {
    int mid, l = left, r = right;
    while(l <= r) {
        mid = l + ((r-l) >> 1);
        if(judge(mid)) r = mid-1;
        else l = mid+1;
    }
    return (l <= right) && (judge(l)) ? l : -1;
}


//最大值(上界),即满足条件的最大值 ,可据上文 "_3_2 返回等于key的右端点" 得到
//此时 judge() 的意义是小于等于下界的值都满足,大于下界的值不满足
//类比上文 !(key < d[mid]) , 即 key >= d[mid] 
int binary_up(int left, int right) {
    int mid, l = left, r = right;
    while(l <= r) {
        mid = l + ((r-l) >> 1);
        if(!judge(mid)) r = mid-1;
        else l = mid+1;
    }
    return (l-1 >= left) && (judge(l-1)) ? l-1 : -1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值