二分查找的思考

<<编程珠玑>>看到一篇关于二分查找算法的分析, 觉得说得特别好,以前数据结构也学过这个算法,下面就把书上的大致意思加上自己的一些研究和看法做个总结.

二分查找的算法可以分为递归与非递归算法.下面的这两种算法的实现形式.

 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //递归算法  
  2. int BinarySearch(int l, int u)  
  3. {  
  4.          int m = 0;  
  5.          if(l > u)  
  6.                    return -1;  
  7.          m = (l + u) / 2;  
  8.          if(key == array[m])  
  9.                    return m;  
  10.          else if(key < array[m])  
  11.          {  
  12.                    u = m - 1;  
  13.                    BinarySearch(l, u);  
  14.          }  
  15.          else if(key > array[m])  
  16.          {  
  17.                    l = m + 1;  
  18.                    BinarySearch(l, u);  
  19.          }  
  20. }  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //非递归算法  
  2. int BinarySearch(int l, int u)  
  3. {  
  4.          int m = 0;  
  5.          while(l <= u)  
  6.          {  
  7.                    m = (l + u) / 2;  
  8.                    if(key == array[m])  
  9.                             return m;  
  10.                    else if(key < array[m])  
  11.                             u = m - 1;  
  12.                    else  
  13.                             l = m + 1;  
  14.          }  
  15.          return (-1);  
  16. }  



递归的算法比较容易理解,但执行速度稍慢,我在vc环境下profile过,性能确实比非递归稍差.

 

<<编程珠玑>>上说90%的程序员写不出无bug的二分查找程序,作者主要基于测试用例来讲的,意思是说测试的情况有很多,要考虑到很多情况. 作者是专门研究算法的,在我看来是有点”钻牛角尖”, 但是如果在实际开发中,应该由此想到代码的健壮性.尤其是嵌入式领域, 一个数据溢出错误就可能导致一台医疗仪器害死一个病人,或者航天飞机上不了天.

 

就拿上面的例子说明代码的健壮性,

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. m = (l+u)/2  

这一行代码就有问题, 如果l+u溢出怎么办(l, u两个数假定都不会溢出) ? 网上看到有人说把l和u声明为无符号数,这显然不行, 因为无符号数也会溢出, 尽管溢出的标志位与有符号位不同. 不管溢出的结果是不是不可预知的,对于二分查找,有无符号数计论下去都是没意义的. 也看到另外一种方法就是

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. m = l + ((u-l)/2).  

这的确是一个不错的方法. 在l和u保证不溢出的情况下, m肯定不会溢出的. 另外如果把(u-l)/2 改成(u-l)>>1 就更好了, 因为了u-l肯定是大于等于零的, 右移和除法的效果是一样的(如果是负数的话,除法和右移有一点区别,这里不说明).


还有就是如果用了计算机所能支持的最大的数据长度还是会有溢出的可能,就干脆加assert, 毕竟一个明确的错误的提示也是代码健壮性的体现.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值