看到http://blog.youkuaiyun.com/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;
}