二分查找引出的问题


看到http://blog.csdn.net/v_july_v/article/details/7093204上有这个问题,自己写了下,发现好多问题。这几天一直在想递归,感觉这个用递归貌似很好些。于是写出了这样的代码:

int my_search1(int *a, int s, int e, int num)
{
        if(s <= e)
        {
                int offset = (s + e)/2;
                if(a[offset] == num)
                        return offset;
                else if(a[offset] > num)
                        my_search1(a, s, offset-1, num);
                else
                        my_search1(a, offset+1, e, num);
        }
        else
                return -1;
}



不对是肯定的。返回的值是一个随机的大整数。想从一个递归的函数中返回,但是递归的返回值是好几层递归以后的函数的返回(想要my_search2(a, 9, 9, 10)的返回值),不是当前调用函数的第一次返回(不是my_search2(a, 0, 9, 10)的返回)。其实my_search2(a, 9, 9, 10)返回值可能已经不再了,返回值在栈上,当时没有保存,返回上层函数这个值就不在了。想了想,这个值不是不再了么,我用一个静态的变量保存下来不就可以了么啊,于是有了下面的代码。

 

int my_search2(int *a, int s, int e, int num)
{
        static int ret = -1;
        if(s <= e)
        {
                int offset = (s + e)/2;
                if(a[offset] == num)
                        ret = offset;
                else if(a[offset] > num)
                        my_search2(a, s, offset-1, num);
                else
                        my_search2(a, offset+1, e, num);
        }
        return ret;
}

 

这里要特别注意,区别不仅仅是多了一个静态的变量,更重要的是每个函数肯定有个返回值!if后面的else没有了,这就保证了,即调用my_search2(a, 0, 9, 10),也是有返回的。如果还是跟上面的代码一样有else同样结果不对。这里my_search2(a, 0, 9, 10)的返回值ret是受其他递归的函数影响的。不过这样写读起来有点难读。下面是参看开始提到文章的代码,没有使用递归,其实感觉如果问题不是特别复杂,没有必要使用递归,递归只是让人读起来很简单,实际效率并不高。要注意的有两点:
1)把等值比较放在最后面,因为绝大多数的情况是不相等的,放在后面可以大大减少比较的次数
2)求两个数的品均值用的a+((b-a)>>2),b>a,这样可以用移位提高效率还可以防止大整数溢出,溢出可能不是发生在开始,可能发生在如果查找的数特别大的情况下,那么a的值就会变大,a+b就可能会溢出。

int binary_search(int *a, int s, int e, int value)
{
        while(s <=e )
        {
                int middle = s + ((e - s)>>1);
                if(a[middle] > value)
                        e = middle - 1;
                else if(a[middle] < value)
                        s = middle + 1;
                else
                        return middle;
        }
        return -1;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值