二分算法总结

二分算法由于其复杂度为O(logN),在实际运算中具有极高的效率。二分算法思想还经常结合其它算法被应用在解决实际项目问题中。例如,对非线性方程求根。

二分算法的思想简单,但编写正确却并不容易。编写二分算法的错误,往往不是因为疏忽错误,而是因为该算法过于灵活却暗藏杀机。轻则程序崩溃,机器停止;重则可能引起致命的损失。

下面先给出错误程序,及样例分析。

错误1:

int bsearch(int *a, int x, int y, int v) {
    int m
    while (x < y) {
        int m = x + (y - x) / 2;
        if (v == a[m])
            return m;
        else if (a[m] > v)
            y = m;
        else
            x = m;
    }
    return -1;
}

假设x = 2,y = 3,a[3] == v。这时候程序将进入死循环,因为m经过运算始终等于2;a[2] < v始终进行x = m;所以x始终小于y。

错误2:

int bsearch(int *a, int x, int y, int v) {
    int m
    while (x < y) {
        int m = x + (y - x) / 2;
        if (v == a[m])
            return m;
        else if (a[m] > v)
            y = m-1;
        else
            x = m+1;
    }
    return -1;
}

假设x = 0,y = 4,a[1] == v。这时候程序将返回-1,而不是1。经过运算m == 2,又因为a[2] > v,所以执行y = m-1。这时候y = 1,循环重新开始,运算后m == 0,经过下面判断语句得到x == 1,这时候循环跳出,忽略了m == 1情况,最后结果错误。
针对错误1的正确程序应该为:


int bsearch(int *a, int x, int y, int v) {  int m
    while (x < y) {
        int m = x + (y - x) / 2;
        if (v == a[m])
            return m;
        else if (a[m] > v)
            y = m;
        else
            x = m + 1;
    }
    return -1; 
}

这里之所以将x = m+1,而不是y = m-1,是因为相邻整数x,y经过m = x + (y + x)/2运算后都是得到的m值总是趋于最小值。例如,x = 2,y = 3,最后得到m == 2。
针对错误2的正确程序应该为:

int bsearch(int *a, int x, int y, int v) {
    int m
    while (x <= y) {
        int m = x + (y - x) / 2;
        if (v == a[m])
            return m;
        else if (a[m] > v)
            y = m - 1;
        else
            x = m + 1;
    }
    return -1;
}

鉴于上面错误2情况,将x < y修改为x <= y后,当x == 1、y == 1时候循环并不会结束,而是继续进行运算得到m == 1的情况,这时候可返回正确解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值